@shware/purchase 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/app-store/index.cjs +2 -0
  2. package/dist/app-store/index.d.cts +2 -1
  3. package/dist/app-store/index.d.mts +2 -1
  4. package/dist/app-store/index.mjs +2 -1
  5. package/dist/app-store/mapper.cjs +47 -0
  6. package/dist/app-store/mapper.cjs.map +1 -0
  7. package/dist/app-store/mapper.d.cts +25 -0
  8. package/dist/app-store/mapper.d.cts.map +1 -0
  9. package/dist/app-store/mapper.d.mts +25 -0
  10. package/dist/app-store/mapper.d.mts.map +1 -0
  11. package/dist/app-store/mapper.mjs +46 -0
  12. package/dist/app-store/mapper.mjs.map +1 -0
  13. package/dist/google-play/index.cjs +2 -0
  14. package/dist/google-play/index.d.cts +2 -2
  15. package/dist/google-play/index.d.mts +2 -2
  16. package/dist/google-play/index.mjs +2 -2
  17. package/dist/google-play/mapper.cjs +48 -0
  18. package/dist/google-play/mapper.cjs.map +1 -1
  19. package/dist/google-play/mapper.d.cts +30 -2
  20. package/dist/google-play/mapper.d.cts.map +1 -1
  21. package/dist/google-play/mapper.d.mts +30 -2
  22. package/dist/google-play/mapper.d.mts.map +1 -1
  23. package/dist/google-play/mapper.mjs +47 -1
  24. package/dist/google-play/mapper.mjs.map +1 -1
  25. package/dist/index.cjs +3 -0
  26. package/dist/index.d.cts +2 -2
  27. package/dist/index.d.mts +2 -2
  28. package/dist/index.mjs +2 -2
  29. package/dist/stripe/index.cjs +1 -0
  30. package/dist/stripe/index.d.cts +4 -3
  31. package/dist/stripe/index.d.mts +4 -3
  32. package/dist/stripe/index.mjs +2 -2
  33. package/dist/stripe/mapper.cjs +18 -0
  34. package/dist/stripe/mapper.cjs.map +1 -1
  35. package/dist/stripe/mapper.d.cts +9 -2
  36. package/dist/stripe/mapper.d.cts.map +1 -1
  37. package/dist/stripe/mapper.d.mts +9 -2
  38. package/dist/stripe/mapper.d.mts.map +1 -1
  39. package/dist/stripe/mapper.mjs +18 -1
  40. package/dist/stripe/mapper.mjs.map +1 -1
  41. package/dist/stripe/schema.cjs +4 -15
  42. package/dist/stripe/schema.cjs.map +1 -1
  43. package/dist/stripe/schema.d.cts +3 -7
  44. package/dist/stripe/schema.d.cts.map +1 -1
  45. package/dist/stripe/schema.d.mts +3 -7
  46. package/dist/stripe/schema.d.mts.map +1 -1
  47. package/dist/stripe/schema.mjs +4 -15
  48. package/dist/stripe/schema.mjs.map +1 -1
  49. package/dist/subscription/index.cjs +25 -0
  50. package/dist/subscription/index.cjs.map +1 -1
  51. package/dist/subscription/index.d.cts +37 -1
  52. package/dist/subscription/index.d.cts.map +1 -1
  53. package/dist/subscription/index.d.mts +37 -1
  54. package/dist/subscription/index.d.mts.map +1 -1
  55. package/dist/subscription/index.mjs +23 -1
  56. package/dist/subscription/index.mjs.map +1 -1
  57. package/package.json +1 -1
@@ -1,5 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_app_store_config = require("./config.cjs");
3
3
  const require_app_store_handler = require("./handler.cjs");
4
+ const require_app_store_mapper = require("./mapper.cjs");
4
5
  exports.AppStoreConfig = require_app_store_config.AppStoreConfig;
5
6
  exports.AppStoreNotificationHandler = require_app_store_handler.AppStoreNotificationHandler;
7
+ exports.mapCancellationDetails = require_app_store_mapper.mapCancellationDetails;
@@ -1,3 +1,4 @@
1
1
  import { AppStoreConfig } from "./config.cjs";
2
2
  import { AppStoreNotificationEvent, AppStoreNotificationHandler } from "./handler.cjs";
3
- export { AppStoreConfig, type AppStoreNotificationEvent, AppStoreNotificationHandler };
3
+ import { AppStoreCancellationSource, mapCancellationDetails } from "./mapper.cjs";
4
+ export { type AppStoreCancellationSource, AppStoreConfig, type AppStoreNotificationEvent, AppStoreNotificationHandler, mapCancellationDetails };
@@ -1,3 +1,4 @@
1
1
  import { AppStoreConfig } from "./config.mjs";
2
2
  import { AppStoreNotificationEvent, AppStoreNotificationHandler } from "./handler.mjs";
3
- export { AppStoreConfig, type AppStoreNotificationEvent, AppStoreNotificationHandler };
3
+ import { AppStoreCancellationSource, mapCancellationDetails } from "./mapper.mjs";
4
+ export { type AppStoreCancellationSource, AppStoreConfig, type AppStoreNotificationEvent, AppStoreNotificationHandler, mapCancellationDetails };
@@ -1,3 +1,4 @@
1
1
  import { AppStoreConfig } from "./config.mjs";
2
2
  import { AppStoreNotificationHandler } from "./handler.mjs";
3
- export { AppStoreConfig, AppStoreNotificationHandler };
3
+ import { mapCancellationDetails } from "./mapper.mjs";
4
+ export { AppStoreConfig, AppStoreNotificationHandler, mapCancellationDetails };
@@ -0,0 +1,47 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/app-store/mapper.ts
3
+ /**
4
+ * Who ended an App Store subscription and why, from the notification that reported it. Null for
5
+ * anything that is not a cancellation, including the customer turning auto-renew back on.
6
+ *
7
+ * ref: [notificationType](https://developer.apple.com/documentation/appstoreservernotifications/notificationtype)
8
+ * ref: [expirationIntent](https://developer.apple.com/documentation/appstoreserverapi/expirationintent)
9
+ */
10
+ function mapCancellationDetails(source) {
11
+ const { notificationType, subtype, expirationIntent } = source;
12
+ const details = (initiator, reason) => ({
13
+ initiator,
14
+ reason,
15
+ feedback: null,
16
+ comment: null
17
+ });
18
+ switch (notificationType) {
19
+ case "DID_CHANGE_RENEWAL_STATUS": return subtype === "AUTO_RENEW_DISABLED" ? details("user", subtype) : null;
20
+ case "EXPIRED": switch (subtype ?? expirationIntentSubtype(expirationIntent)) {
21
+ case "VOLUNTARY": return details("user", "VOLUNTARY");
22
+ case "BILLING_RETRY": return details("system", "BILLING_RETRY");
23
+ case "PRICE_INCREASE": return details("user", "PRICE_INCREASE");
24
+ case "PRODUCT_NOT_FOR_SALE": return details("developer", "PRODUCT_NOT_FOR_SALE");
25
+ default: return details("system", "EXPIRED");
26
+ }
27
+ case "DID_FAIL_TO_RENEW":
28
+ case "GRACE_PERIOD_EXPIRED":
29
+ case "REFUND":
30
+ case "REVOKE": return details("system", notificationType);
31
+ default: return null;
32
+ }
33
+ }
34
+ /** The EXPIRED subtype Apple would have sent for an `expirationIntent`. */
35
+ function expirationIntentSubtype(intent) {
36
+ switch (intent) {
37
+ case 1: return "VOLUNTARY";
38
+ case 2: return "BILLING_RETRY";
39
+ case 3: return "PRICE_INCREASE";
40
+ case 4: return "PRODUCT_NOT_FOR_SALE";
41
+ default: return;
42
+ }
43
+ }
44
+ //#endregion
45
+ exports.mapCancellationDetails = mapCancellationDetails;
46
+
47
+ //# sourceMappingURL=mapper.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.cjs","names":[],"sources":["../../src/app-store/mapper.ts"],"sourcesContent":["import type { CancellationDetails } from '../subscription/index';\n\n/**\n * The App Store Server Notification fields that say why a subscription stops renewing: the\n * notification type and subtype, plus `expirationIntent` from the renewal info once it has\n * expired. Strings and numbers as Apple sends them, so this needs no runtime import of the\n * App Store Server Library.\n */\nexport interface AppStoreCancellationSource {\n notificationType: string;\n subtype?: string | null;\n /** `JWSRenewalInfoDecodedPayload.expirationIntent`: 1 customer, 2 billing, 3 price increase, 4 unavailable, 5 other. */\n expirationIntent?: number | null;\n}\n\n/**\n * Who ended an App Store subscription and why, from the notification that reported it. Null for\n * anything that is not a cancellation, including the customer turning auto-renew back on.\n *\n * ref: [notificationType](https://developer.apple.com/documentation/appstoreservernotifications/notificationtype)\n * ref: [expirationIntent](https://developer.apple.com/documentation/appstoreserverapi/expirationintent)\n */\nexport function mapCancellationDetails(\n source: AppStoreCancellationSource\n): CancellationDetails | null {\n const { notificationType, subtype, expirationIntent } = source;\n const details = (initiator: CancellationDetails['initiator'], reason: string) => ({\n initiator,\n reason,\n feedback: null,\n comment: null,\n });\n\n switch (notificationType) {\n case 'DID_CHANGE_RENEWAL_STATUS':\n return subtype === 'AUTO_RENEW_DISABLED' ? details('user', subtype) : null;\n case 'EXPIRED':\n switch (subtype ?? expirationIntentSubtype(expirationIntent)) {\n case 'VOLUNTARY':\n return details('user', 'VOLUNTARY');\n case 'BILLING_RETRY':\n return details('system', 'BILLING_RETRY');\n case 'PRICE_INCREASE':\n return details('user', 'PRICE_INCREASE');\n case 'PRODUCT_NOT_FOR_SALE':\n return details('developer', 'PRODUCT_NOT_FOR_SALE');\n default:\n return details('system', 'EXPIRED');\n }\n case 'DID_FAIL_TO_RENEW':\n case 'GRACE_PERIOD_EXPIRED':\n case 'REFUND':\n case 'REVOKE':\n return details('system', notificationType);\n default:\n return null;\n }\n}\n\n/** The EXPIRED subtype Apple would have sent for an `expirationIntent`. */\nfunction expirationIntentSubtype(intent: number | null | undefined) {\n switch (intent) {\n case 1:\n return 'VOLUNTARY';\n case 2:\n return 'BILLING_RETRY';\n case 3:\n return 'PRICE_INCREASE';\n case 4:\n return 'PRODUCT_NOT_FOR_SALE';\n default:\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;AAsBA,SAAgB,uBACd,QAC4B;CAC5B,MAAM,EAAE,kBAAkB,SAAS,qBAAqB;CACxD,MAAM,WAAW,WAA6C,YAAoB;EAChF;EACA;EACA,UAAU;EACV,SAAS;CACX;CAEA,QAAQ,kBAAR;EACE,KAAK,6BACH,OAAO,YAAY,wBAAwB,QAAQ,QAAQ,OAAO,IAAI;EACxE,KAAK,WACH,QAAQ,WAAW,wBAAwB,gBAAgB,GAA3D;GACE,KAAK,aACH,OAAO,QAAQ,QAAQ,WAAW;GACpC,KAAK,iBACH,OAAO,QAAQ,UAAU,eAAe;GAC1C,KAAK,kBACH,OAAO,QAAQ,QAAQ,gBAAgB;GACzC,KAAK,wBACH,OAAO,QAAQ,aAAa,sBAAsB;GACpD,SACE,OAAO,QAAQ,UAAU,SAAS;EACtC;EACF,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,UACH,OAAO,QAAQ,UAAU,gBAAgB;EAC3C,SACE,OAAO;CACX;AACF;;AAGA,SAAS,wBAAwB,QAAmC;CAClE,QAAQ,QAAR;EACE,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,SACE;CACJ;AACF"}
@@ -0,0 +1,25 @@
1
+ import { CancellationDetails } from "../subscription/index.cjs";
2
+ //#region src/app-store/mapper.d.ts
3
+ /**
4
+ * The App Store Server Notification fields that say why a subscription stops renewing: the
5
+ * notification type and subtype, plus `expirationIntent` from the renewal info once it has
6
+ * expired. Strings and numbers as Apple sends them, so this needs no runtime import of the
7
+ * App Store Server Library.
8
+ */
9
+ interface AppStoreCancellationSource {
10
+ notificationType: string;
11
+ subtype?: string | null;
12
+ /** `JWSRenewalInfoDecodedPayload.expirationIntent`: 1 customer, 2 billing, 3 price increase, 4 unavailable, 5 other. */
13
+ expirationIntent?: number | null;
14
+ }
15
+ /**
16
+ * Who ended an App Store subscription and why, from the notification that reported it. Null for
17
+ * anything that is not a cancellation, including the customer turning auto-renew back on.
18
+ *
19
+ * ref: [notificationType](https://developer.apple.com/documentation/appstoreservernotifications/notificationtype)
20
+ * ref: [expirationIntent](https://developer.apple.com/documentation/appstoreserverapi/expirationintent)
21
+ */
22
+ declare function mapCancellationDetails(source: AppStoreCancellationSource): CancellationDetails | null;
23
+ //#endregion
24
+ export { AppStoreCancellationSource, mapCancellationDetails };
25
+ //# sourceMappingURL=mapper.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.d.cts","names":[],"sources":["../../src/app-store/mapper.ts"],"mappings":";;;;;;;;UAQiB;EACf;EACA;;EAEA;;;;;;;;;iBAUc,uBACd,QAAQ,6BACP"}
@@ -0,0 +1,25 @@
1
+ import { CancellationDetails } from "../subscription/index.mjs";
2
+ //#region src/app-store/mapper.d.ts
3
+ /**
4
+ * The App Store Server Notification fields that say why a subscription stops renewing: the
5
+ * notification type and subtype, plus `expirationIntent` from the renewal info once it has
6
+ * expired. Strings and numbers as Apple sends them, so this needs no runtime import of the
7
+ * App Store Server Library.
8
+ */
9
+ interface AppStoreCancellationSource {
10
+ notificationType: string;
11
+ subtype?: string | null;
12
+ /** `JWSRenewalInfoDecodedPayload.expirationIntent`: 1 customer, 2 billing, 3 price increase, 4 unavailable, 5 other. */
13
+ expirationIntent?: number | null;
14
+ }
15
+ /**
16
+ * Who ended an App Store subscription and why, from the notification that reported it. Null for
17
+ * anything that is not a cancellation, including the customer turning auto-renew back on.
18
+ *
19
+ * ref: [notificationType](https://developer.apple.com/documentation/appstoreservernotifications/notificationtype)
20
+ * ref: [expirationIntent](https://developer.apple.com/documentation/appstoreserverapi/expirationintent)
21
+ */
22
+ declare function mapCancellationDetails(source: AppStoreCancellationSource): CancellationDetails | null;
23
+ //#endregion
24
+ export { AppStoreCancellationSource, mapCancellationDetails };
25
+ //# sourceMappingURL=mapper.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.d.mts","names":[],"sources":["../../src/app-store/mapper.ts"],"mappings":";;;;;;;;UAQiB;EACf;EACA;;EAEA;;;;;;;;;iBAUc,uBACd,QAAQ,6BACP"}
@@ -0,0 +1,46 @@
1
+ //#region src/app-store/mapper.ts
2
+ /**
3
+ * Who ended an App Store subscription and why, from the notification that reported it. Null for
4
+ * anything that is not a cancellation, including the customer turning auto-renew back on.
5
+ *
6
+ * ref: [notificationType](https://developer.apple.com/documentation/appstoreservernotifications/notificationtype)
7
+ * ref: [expirationIntent](https://developer.apple.com/documentation/appstoreserverapi/expirationintent)
8
+ */
9
+ function mapCancellationDetails(source) {
10
+ const { notificationType, subtype, expirationIntent } = source;
11
+ const details = (initiator, reason) => ({
12
+ initiator,
13
+ reason,
14
+ feedback: null,
15
+ comment: null
16
+ });
17
+ switch (notificationType) {
18
+ case "DID_CHANGE_RENEWAL_STATUS": return subtype === "AUTO_RENEW_DISABLED" ? details("user", subtype) : null;
19
+ case "EXPIRED": switch (subtype ?? expirationIntentSubtype(expirationIntent)) {
20
+ case "VOLUNTARY": return details("user", "VOLUNTARY");
21
+ case "BILLING_RETRY": return details("system", "BILLING_RETRY");
22
+ case "PRICE_INCREASE": return details("user", "PRICE_INCREASE");
23
+ case "PRODUCT_NOT_FOR_SALE": return details("developer", "PRODUCT_NOT_FOR_SALE");
24
+ default: return details("system", "EXPIRED");
25
+ }
26
+ case "DID_FAIL_TO_RENEW":
27
+ case "GRACE_PERIOD_EXPIRED":
28
+ case "REFUND":
29
+ case "REVOKE": return details("system", notificationType);
30
+ default: return null;
31
+ }
32
+ }
33
+ /** The EXPIRED subtype Apple would have sent for an `expirationIntent`. */
34
+ function expirationIntentSubtype(intent) {
35
+ switch (intent) {
36
+ case 1: return "VOLUNTARY";
37
+ case 2: return "BILLING_RETRY";
38
+ case 3: return "PRICE_INCREASE";
39
+ case 4: return "PRODUCT_NOT_FOR_SALE";
40
+ default: return;
41
+ }
42
+ }
43
+ //#endregion
44
+ export { mapCancellationDetails };
45
+
46
+ //# sourceMappingURL=mapper.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.mjs","names":[],"sources":["../../src/app-store/mapper.ts"],"sourcesContent":["import type { CancellationDetails } from '../subscription/index';\n\n/**\n * The App Store Server Notification fields that say why a subscription stops renewing: the\n * notification type and subtype, plus `expirationIntent` from the renewal info once it has\n * expired. Strings and numbers as Apple sends them, so this needs no runtime import of the\n * App Store Server Library.\n */\nexport interface AppStoreCancellationSource {\n notificationType: string;\n subtype?: string | null;\n /** `JWSRenewalInfoDecodedPayload.expirationIntent`: 1 customer, 2 billing, 3 price increase, 4 unavailable, 5 other. */\n expirationIntent?: number | null;\n}\n\n/**\n * Who ended an App Store subscription and why, from the notification that reported it. Null for\n * anything that is not a cancellation, including the customer turning auto-renew back on.\n *\n * ref: [notificationType](https://developer.apple.com/documentation/appstoreservernotifications/notificationtype)\n * ref: [expirationIntent](https://developer.apple.com/documentation/appstoreserverapi/expirationintent)\n */\nexport function mapCancellationDetails(\n source: AppStoreCancellationSource\n): CancellationDetails | null {\n const { notificationType, subtype, expirationIntent } = source;\n const details = (initiator: CancellationDetails['initiator'], reason: string) => ({\n initiator,\n reason,\n feedback: null,\n comment: null,\n });\n\n switch (notificationType) {\n case 'DID_CHANGE_RENEWAL_STATUS':\n return subtype === 'AUTO_RENEW_DISABLED' ? details('user', subtype) : null;\n case 'EXPIRED':\n switch (subtype ?? expirationIntentSubtype(expirationIntent)) {\n case 'VOLUNTARY':\n return details('user', 'VOLUNTARY');\n case 'BILLING_RETRY':\n return details('system', 'BILLING_RETRY');\n case 'PRICE_INCREASE':\n return details('user', 'PRICE_INCREASE');\n case 'PRODUCT_NOT_FOR_SALE':\n return details('developer', 'PRODUCT_NOT_FOR_SALE');\n default:\n return details('system', 'EXPIRED');\n }\n case 'DID_FAIL_TO_RENEW':\n case 'GRACE_PERIOD_EXPIRED':\n case 'REFUND':\n case 'REVOKE':\n return details('system', notificationType);\n default:\n return null;\n }\n}\n\n/** The EXPIRED subtype Apple would have sent for an `expirationIntent`. */\nfunction expirationIntentSubtype(intent: number | null | undefined) {\n switch (intent) {\n case 1:\n return 'VOLUNTARY';\n case 2:\n return 'BILLING_RETRY';\n case 3:\n return 'PRICE_INCREASE';\n case 4:\n return 'PRODUCT_NOT_FOR_SALE';\n default:\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;AAsBA,SAAgB,uBACd,QAC4B;CAC5B,MAAM,EAAE,kBAAkB,SAAS,qBAAqB;CACxD,MAAM,WAAW,WAA6C,YAAoB;EAChF;EACA;EACA,UAAU;EACV,SAAS;CACX;CAEA,QAAQ,kBAAR;EACE,KAAK,6BACH,OAAO,YAAY,wBAAwB,QAAQ,QAAQ,OAAO,IAAI;EACxE,KAAK,WACH,QAAQ,WAAW,wBAAwB,gBAAgB,GAA3D;GACE,KAAK,aACH,OAAO,QAAQ,QAAQ,WAAW;GACpC,KAAK,iBACH,OAAO,QAAQ,UAAU,eAAe;GAC1C,KAAK,kBACH,OAAO,QAAQ,QAAQ,gBAAgB;GACzC,KAAK,wBACH,OAAO,QAAQ,aAAa,sBAAsB;GACpD,SACE,OAAO,QAAQ,UAAU,SAAS;EACtC;EACF,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,UACH,OAAO,QAAQ,UAAU,gBAAgB;EAC3C,SACE,OAAO;CACX;AACF;;AAGA,SAAS,wBAAwB,QAAmC;CAClE,QAAQ,QAAR;EACE,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,KAAK,GACH,OAAO;EACT,SACE;CACJ;AACF"}
@@ -8,4 +8,6 @@ exports.OneTimeProductNotificationType = require_google_play_real_time_developer
8
8
  exports.SubscriptionNotificationType = require_google_play_real_time_developer_notification.SubscriptionNotificationType;
9
9
  exports.VoidedPurchaseProductType = require_google_play_real_time_developer_notification.VoidedPurchaseProductType;
10
10
  exports.VoidedPurchaseRefundType = require_google_play_real_time_developer_notification.VoidedPurchaseRefundType;
11
+ exports.mapCanceledAt = require_google_play_mapper.mapCanceledAt;
12
+ exports.mapCancellationDetails = require_google_play_mapper.mapCancellationDetails;
11
13
  exports.mapSubscriptionStatus = require_google_play_mapper.mapSubscriptionStatus;
@@ -1,4 +1,4 @@
1
1
  import { GooglePlayConfig } from "./config.cjs";
2
2
  import { DeveloperNotification, GOOGLE_PLAY_SUBSCRIPTION_STATES, GooglePlaySubscriptionState, OneTimeProductNotification, OneTimeProductNotificationType, PubsubMessage, SubscriptionNotification, SubscriptionNotificationType, TestNotification, VoidedPurchaseNotification, VoidedPurchaseProductType, VoidedPurchaseRefundType } from "./real-time-developer-notification.cjs";
3
- import { mapSubscriptionStatus } from "./mapper.cjs";
4
- export { type DeveloperNotification, GOOGLE_PLAY_SUBSCRIPTION_STATES, GooglePlayConfig, type GooglePlaySubscriptionState, type OneTimeProductNotification, OneTimeProductNotificationType, type PubsubMessage, type SubscriptionNotification, SubscriptionNotificationType, type TestNotification, type VoidedPurchaseNotification, VoidedPurchaseProductType, VoidedPurchaseRefundType, mapSubscriptionStatus };
3
+ import { CanceledStateContext, mapCanceledAt, mapCancellationDetails, mapSubscriptionStatus } from "./mapper.cjs";
4
+ export { type CanceledStateContext, type DeveloperNotification, GOOGLE_PLAY_SUBSCRIPTION_STATES, GooglePlayConfig, type GooglePlaySubscriptionState, type OneTimeProductNotification, OneTimeProductNotificationType, type PubsubMessage, type SubscriptionNotification, SubscriptionNotificationType, type TestNotification, type VoidedPurchaseNotification, VoidedPurchaseProductType, VoidedPurchaseRefundType, mapCanceledAt, mapCancellationDetails, mapSubscriptionStatus };
@@ -1,4 +1,4 @@
1
1
  import { GooglePlayConfig } from "./config.mjs";
2
2
  import { DeveloperNotification, GOOGLE_PLAY_SUBSCRIPTION_STATES, GooglePlaySubscriptionState, OneTimeProductNotification, OneTimeProductNotificationType, PubsubMessage, SubscriptionNotification, SubscriptionNotificationType, TestNotification, VoidedPurchaseNotification, VoidedPurchaseProductType, VoidedPurchaseRefundType } from "./real-time-developer-notification.mjs";
3
- import { mapSubscriptionStatus } from "./mapper.mjs";
4
- export { type DeveloperNotification, GOOGLE_PLAY_SUBSCRIPTION_STATES, GooglePlayConfig, type GooglePlaySubscriptionState, type OneTimeProductNotification, OneTimeProductNotificationType, type PubsubMessage, type SubscriptionNotification, SubscriptionNotificationType, type TestNotification, type VoidedPurchaseNotification, VoidedPurchaseProductType, VoidedPurchaseRefundType, mapSubscriptionStatus };
3
+ import { CanceledStateContext, mapCanceledAt, mapCancellationDetails, mapSubscriptionStatus } from "./mapper.mjs";
4
+ export { type CanceledStateContext, type DeveloperNotification, GOOGLE_PLAY_SUBSCRIPTION_STATES, GooglePlayConfig, type GooglePlaySubscriptionState, type OneTimeProductNotification, OneTimeProductNotificationType, type PubsubMessage, type SubscriptionNotification, SubscriptionNotificationType, type TestNotification, type VoidedPurchaseNotification, VoidedPurchaseProductType, VoidedPurchaseRefundType, mapCanceledAt, mapCancellationDetails, mapSubscriptionStatus };
@@ -1,4 +1,4 @@
1
1
  import { GooglePlayConfig } from "./config.mjs";
2
2
  import { GOOGLE_PLAY_SUBSCRIPTION_STATES, OneTimeProductNotificationType, SubscriptionNotificationType, VoidedPurchaseProductType, VoidedPurchaseRefundType } from "./real-time-developer-notification.mjs";
3
- import { mapSubscriptionStatus } from "./mapper.mjs";
4
- export { GOOGLE_PLAY_SUBSCRIPTION_STATES, GooglePlayConfig, OneTimeProductNotificationType, SubscriptionNotificationType, VoidedPurchaseProductType, VoidedPurchaseRefundType, mapSubscriptionStatus };
3
+ import { mapCanceledAt, mapCancellationDetails, mapSubscriptionStatus } from "./mapper.mjs";
4
+ export { GOOGLE_PLAY_SUBSCRIPTION_STATES, GooglePlayConfig, OneTimeProductNotificationType, SubscriptionNotificationType, VoidedPurchaseProductType, VoidedPurchaseRefundType, mapCanceledAt, mapCancellationDetails, mapSubscriptionStatus };
@@ -13,7 +13,55 @@ function mapSubscriptionStatus(state) {
13
13
  default: throw new Error(`Unknown Google Play subscription state: ${state}`);
14
14
  }
15
15
  }
16
+ /** Play's cancel-survey answers in the shared vocabulary. */
17
+ const SURVEY_FEEDBACK = {
18
+ CANCEL_SURVEY_REASON_NOT_ENOUGH_USAGE: "unused",
19
+ CANCEL_SURVEY_REASON_TECHNICAL_ISSUES: "low_quality",
20
+ CANCEL_SURVEY_REASON_COST_RELATED: "too_expensive",
21
+ CANCEL_SURVEY_REASON_FOUND_BETTER_APP: "switched_service",
22
+ CANCEL_SURVEY_REASON_OTHERS: "other"
23
+ };
24
+ /**
25
+ * Why a Play subscription stopped renewing. The Play Store asks the user for a reason on cancel
26
+ * (and for free text when it is "Other"), which comes back in `cancelSurveyResult`. Null while
27
+ * the subscription renews, and for a replacement: that is the linked purchase taking over, not a
28
+ * cancellation to report.
29
+ */
30
+ function mapCancellationDetails(context) {
31
+ if (!context) return null;
32
+ if (context.userInitiatedCancellation) {
33
+ const survey = context.userInitiatedCancellation.cancelSurveyResult;
34
+ return {
35
+ initiator: "user",
36
+ reason: survey?.reason ?? null,
37
+ feedback: survey?.reason && SURVEY_FEEDBACK[survey.reason] || null,
38
+ comment: survey?.reasonUserInput ?? null
39
+ };
40
+ }
41
+ if (context.systemInitiatedCancellation) return {
42
+ initiator: "system",
43
+ reason: "SYSTEM_INITIATED",
44
+ feedback: null,
45
+ comment: null
46
+ };
47
+ if (context.developerInitiatedCancellation) return {
48
+ initiator: "developer",
49
+ reason: "DEVELOPER_INITIATED",
50
+ feedback: null,
51
+ comment: null
52
+ };
53
+ return null;
54
+ }
55
+ /**
56
+ * When the subscription was cancelled. Only a user cancellation carries the time; for the others
57
+ * the caller falls back to when it learnt of it.
58
+ */
59
+ function mapCanceledAt(context) {
60
+ return context?.userInitiatedCancellation?.cancelTime ?? null;
61
+ }
16
62
  //#endregion
63
+ exports.mapCanceledAt = mapCanceledAt;
64
+ exports.mapCancellationDetails = mapCancellationDetails;
17
65
  exports.mapSubscriptionStatus = mapSubscriptionStatus;
18
66
 
19
67
  //# sourceMappingURL=mapper.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"mapper.cjs","names":[],"sources":["../../src/google-play/mapper.ts"],"sourcesContent":["import type { SubscriptionStatus } from '../subscription/index';\nimport type { GooglePlaySubscriptionState } from './real-time-developer-notification';\n\nexport function mapSubscriptionStatus(state: GooglePlaySubscriptionState): SubscriptionStatus {\n switch (state) {\n case 'SUBSCRIPTION_STATE_PENDING':\n return 'PENDING';\n case 'SUBSCRIPTION_STATE_ACTIVE':\n return 'ACTIVE';\n case 'SUBSCRIPTION_STATE_PAUSED':\n return 'PAUSED';\n case 'SUBSCRIPTION_STATE_IN_GRACE_PERIOD':\n return 'IN_GRACE_PERIOD';\n case 'SUBSCRIPTION_STATE_ON_HOLD':\n return 'ON_HOLD';\n case 'SUBSCRIPTION_STATE_CANCELED':\n return 'CANCELED';\n case 'SUBSCRIPTION_STATE_EXPIRED':\n return 'EXPIRED';\n case 'SUBSCRIPTION_STATE_PENDING_PURCHASE_CANCELED':\n return 'PENDING_PURCHASE_CANCELED';\n default:\n throw new Error(`Unknown Google Play subscription state: ${state}`);\n }\n}\n"],"mappings":";;AAGA,SAAgB,sBAAsB,OAAwD;CAC5F,QAAQ,OAAR;EACE,KAAK,8BACH,OAAO;EACT,KAAK,6BACH,OAAO;EACT,KAAK,6BACH,OAAO;EACT,KAAK,sCACH,OAAO;EACT,KAAK,8BACH,OAAO;EACT,KAAK,+BACH,OAAO;EACT,KAAK,8BACH,OAAO;EACT,KAAK,gDACH,OAAO;EACT,SACE,MAAM,IAAI,MAAM,2CAA2C,OAAO;CACtE;AACF"}
1
+ {"version":3,"file":"mapper.cjs","names":[],"sources":["../../src/google-play/mapper.ts"],"sourcesContent":["import type { CancellationDetails, SubscriptionStatus } from '../subscription/index';\nimport type { GooglePlaySubscriptionState } from './real-time-developer-notification';\n\nexport function mapSubscriptionStatus(state: GooglePlaySubscriptionState): SubscriptionStatus {\n switch (state) {\n case 'SUBSCRIPTION_STATE_PENDING':\n return 'PENDING';\n case 'SUBSCRIPTION_STATE_ACTIVE':\n return 'ACTIVE';\n case 'SUBSCRIPTION_STATE_PAUSED':\n return 'PAUSED';\n case 'SUBSCRIPTION_STATE_IN_GRACE_PERIOD':\n return 'IN_GRACE_PERIOD';\n case 'SUBSCRIPTION_STATE_ON_HOLD':\n return 'ON_HOLD';\n case 'SUBSCRIPTION_STATE_CANCELED':\n return 'CANCELED';\n case 'SUBSCRIPTION_STATE_EXPIRED':\n return 'EXPIRED';\n case 'SUBSCRIPTION_STATE_PENDING_PURCHASE_CANCELED':\n return 'PENDING_PURCHASE_CANCELED';\n default:\n throw new Error(`Unknown Google Play subscription state: ${state}`);\n }\n}\n\n/** Play's cancel-survey answers in the shared vocabulary. */\nconst SURVEY_FEEDBACK: Record<string, CancellationDetails['feedback']> = {\n CANCEL_SURVEY_REASON_NOT_ENOUGH_USAGE: 'unused',\n CANCEL_SURVEY_REASON_TECHNICAL_ISSUES: 'low_quality',\n CANCEL_SURVEY_REASON_COST_RELATED: 'too_expensive',\n CANCEL_SURVEY_REASON_FOUND_BETTER_APP: 'switched_service',\n CANCEL_SURVEY_REASON_OTHERS: 'other',\n};\n\n/**\n * `canceledStateContext` of `purchases.subscriptionsv2.get`, declared structurally so this\n * module does not depend on the Play Developer API client.\n */\nexport interface CanceledStateContext {\n userInitiatedCancellation?: {\n cancelTime?: string | null;\n cancelSurveyResult?: { reason?: string | null; reasonUserInput?: string | null } | null;\n } | null;\n systemInitiatedCancellation?: object | null;\n developerInitiatedCancellation?: object | null;\n replacementCancellation?: object | null;\n}\n\n/**\n * Why a Play subscription stopped renewing. The Play Store asks the user for a reason on cancel\n * (and for free text when it is \"Other\"), which comes back in `cancelSurveyResult`. Null while\n * the subscription renews, and for a replacement: that is the linked purchase taking over, not a\n * cancellation to report.\n */\nexport function mapCancellationDetails(\n context: CanceledStateContext | null | undefined\n): CancellationDetails | null {\n if (!context) return null;\n if (context.userInitiatedCancellation) {\n const survey = context.userInitiatedCancellation.cancelSurveyResult;\n return {\n initiator: 'user',\n reason: survey?.reason ?? null,\n feedback: (survey?.reason && SURVEY_FEEDBACK[survey.reason]) || null,\n comment: survey?.reasonUserInput ?? null,\n };\n }\n if (context.systemInitiatedCancellation) {\n return { initiator: 'system', reason: 'SYSTEM_INITIATED', feedback: null, comment: null };\n }\n if (context.developerInitiatedCancellation) {\n return { initiator: 'developer', reason: 'DEVELOPER_INITIATED', feedback: null, comment: null };\n }\n return null;\n}\n\n/**\n * When the subscription was cancelled. Only a user cancellation carries the time; for the others\n * the caller falls back to when it learnt of it.\n */\nexport function mapCanceledAt(context: CanceledStateContext | null | undefined): string | null {\n return context?.userInitiatedCancellation?.cancelTime ?? null;\n}\n"],"mappings":";;AAGA,SAAgB,sBAAsB,OAAwD;CAC5F,QAAQ,OAAR;EACE,KAAK,8BACH,OAAO;EACT,KAAK,6BACH,OAAO;EACT,KAAK,6BACH,OAAO;EACT,KAAK,sCACH,OAAO;EACT,KAAK,8BACH,OAAO;EACT,KAAK,+BACH,OAAO;EACT,KAAK,8BACH,OAAO;EACT,KAAK,gDACH,OAAO;EACT,SACE,MAAM,IAAI,MAAM,2CAA2C,OAAO;CACtE;AACF;;AAGA,MAAM,kBAAmE;CACvE,uCAAuC;CACvC,uCAAuC;CACvC,mCAAmC;CACnC,uCAAuC;CACvC,6BAA6B;AAC/B;;;;;;;AAsBA,SAAgB,uBACd,SAC4B;CAC5B,IAAI,CAAC,SAAS,OAAO;CACrB,IAAI,QAAQ,2BAA2B;EACrC,MAAM,SAAS,QAAQ,0BAA0B;EACjD,OAAO;GACL,WAAW;GACX,QAAQ,QAAQ,UAAU;GAC1B,UAAW,QAAQ,UAAU,gBAAgB,OAAO,WAAY;GAChE,SAAS,QAAQ,mBAAmB;EACtC;CACF;CACA,IAAI,QAAQ,6BACV,OAAO;EAAE,WAAW;EAAU,QAAQ;EAAoB,UAAU;EAAM,SAAS;CAAK;CAE1F,IAAI,QAAQ,gCACV,OAAO;EAAE,WAAW;EAAa,QAAQ;EAAuB,UAAU;EAAM,SAAS;CAAK;CAEhG,OAAO;AACT;;;;;AAMA,SAAgB,cAAc,SAAiE;CAC7F,OAAO,SAAS,2BAA2B,cAAc;AAC3D"}
@@ -1,7 +1,35 @@
1
+ import { CancellationDetails, SubscriptionStatus } from "../subscription/index.cjs";
1
2
  import { GooglePlaySubscriptionState } from "./real-time-developer-notification.cjs";
2
- import { SubscriptionStatus } from "../subscription/index.cjs";
3
3
  //#region src/google-play/mapper.d.ts
4
4
  declare function mapSubscriptionStatus(state: GooglePlaySubscriptionState): SubscriptionStatus;
5
+ /**
6
+ * `canceledStateContext` of `purchases.subscriptionsv2.get`, declared structurally so this
7
+ * module does not depend on the Play Developer API client.
8
+ */
9
+ interface CanceledStateContext {
10
+ userInitiatedCancellation?: {
11
+ cancelTime?: string | null;
12
+ cancelSurveyResult?: {
13
+ reason?: string | null;
14
+ reasonUserInput?: string | null;
15
+ } | null;
16
+ } | null;
17
+ systemInitiatedCancellation?: object | null;
18
+ developerInitiatedCancellation?: object | null;
19
+ replacementCancellation?: object | null;
20
+ }
21
+ /**
22
+ * Why a Play subscription stopped renewing. The Play Store asks the user for a reason on cancel
23
+ * (and for free text when it is "Other"), which comes back in `cancelSurveyResult`. Null while
24
+ * the subscription renews, and for a replacement: that is the linked purchase taking over, not a
25
+ * cancellation to report.
26
+ */
27
+ declare function mapCancellationDetails(context: CanceledStateContext | null | undefined): CancellationDetails | null;
28
+ /**
29
+ * When the subscription was cancelled. Only a user cancellation carries the time; for the others
30
+ * the caller falls back to when it learnt of it.
31
+ */
32
+ declare function mapCanceledAt(context: CanceledStateContext | null | undefined): string | null;
5
33
  //#endregion
6
- export { mapSubscriptionStatus };
34
+ export { CanceledStateContext, mapCanceledAt, mapCancellationDetails, mapSubscriptionStatus };
7
35
  //# sourceMappingURL=mapper.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mapper.d.cts","names":[],"sources":["../../src/google-play/mapper.ts"],"mappings":";;;iBAGgB,sBAAsB,OAAO,8BAA8B"}
1
+ {"version":3,"file":"mapper.d.cts","names":[],"sources":["../../src/google-play/mapper.ts"],"mappings":";;;iBAGgB,sBAAsB,OAAO,8BAA8B;;;;;UAoC1D;EACf;IACE;IACA;MAAuB;MAAwB;;;EAEjD;EACA;EACA;;;;;;;;iBASc,uBACd,SAAS,0CACR;;;;;iBAwBa,cAAc,SAAS"}
@@ -1,7 +1,35 @@
1
+ import { CancellationDetails, SubscriptionStatus } from "../subscription/index.mjs";
1
2
  import { GooglePlaySubscriptionState } from "./real-time-developer-notification.mjs";
2
- import { SubscriptionStatus } from "../subscription/index.mjs";
3
3
  //#region src/google-play/mapper.d.ts
4
4
  declare function mapSubscriptionStatus(state: GooglePlaySubscriptionState): SubscriptionStatus;
5
+ /**
6
+ * `canceledStateContext` of `purchases.subscriptionsv2.get`, declared structurally so this
7
+ * module does not depend on the Play Developer API client.
8
+ */
9
+ interface CanceledStateContext {
10
+ userInitiatedCancellation?: {
11
+ cancelTime?: string | null;
12
+ cancelSurveyResult?: {
13
+ reason?: string | null;
14
+ reasonUserInput?: string | null;
15
+ } | null;
16
+ } | null;
17
+ systemInitiatedCancellation?: object | null;
18
+ developerInitiatedCancellation?: object | null;
19
+ replacementCancellation?: object | null;
20
+ }
21
+ /**
22
+ * Why a Play subscription stopped renewing. The Play Store asks the user for a reason on cancel
23
+ * (and for free text when it is "Other"), which comes back in `cancelSurveyResult`. Null while
24
+ * the subscription renews, and for a replacement: that is the linked purchase taking over, not a
25
+ * cancellation to report.
26
+ */
27
+ declare function mapCancellationDetails(context: CanceledStateContext | null | undefined): CancellationDetails | null;
28
+ /**
29
+ * When the subscription was cancelled. Only a user cancellation carries the time; for the others
30
+ * the caller falls back to when it learnt of it.
31
+ */
32
+ declare function mapCanceledAt(context: CanceledStateContext | null | undefined): string | null;
5
33
  //#endregion
6
- export { mapSubscriptionStatus };
34
+ export { CanceledStateContext, mapCanceledAt, mapCancellationDetails, mapSubscriptionStatus };
7
35
  //# sourceMappingURL=mapper.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mapper.d.mts","names":[],"sources":["../../src/google-play/mapper.ts"],"mappings":";;;iBAGgB,sBAAsB,OAAO,8BAA8B"}
1
+ {"version":3,"file":"mapper.d.mts","names":[],"sources":["../../src/google-play/mapper.ts"],"mappings":";;;iBAGgB,sBAAsB,OAAO,8BAA8B;;;;;UAoC1D;EACf;IACE;IACA;MAAuB;MAAwB;;;EAEjD;EACA;EACA;;;;;;;;iBASc,uBACd,SAAS,0CACR;;;;;iBAwBa,cAAc,SAAS"}
@@ -12,7 +12,53 @@ function mapSubscriptionStatus(state) {
12
12
  default: throw new Error(`Unknown Google Play subscription state: ${state}`);
13
13
  }
14
14
  }
15
+ /** Play's cancel-survey answers in the shared vocabulary. */
16
+ const SURVEY_FEEDBACK = {
17
+ CANCEL_SURVEY_REASON_NOT_ENOUGH_USAGE: "unused",
18
+ CANCEL_SURVEY_REASON_TECHNICAL_ISSUES: "low_quality",
19
+ CANCEL_SURVEY_REASON_COST_RELATED: "too_expensive",
20
+ CANCEL_SURVEY_REASON_FOUND_BETTER_APP: "switched_service",
21
+ CANCEL_SURVEY_REASON_OTHERS: "other"
22
+ };
23
+ /**
24
+ * Why a Play subscription stopped renewing. The Play Store asks the user for a reason on cancel
25
+ * (and for free text when it is "Other"), which comes back in `cancelSurveyResult`. Null while
26
+ * the subscription renews, and for a replacement: that is the linked purchase taking over, not a
27
+ * cancellation to report.
28
+ */
29
+ function mapCancellationDetails(context) {
30
+ if (!context) return null;
31
+ if (context.userInitiatedCancellation) {
32
+ const survey = context.userInitiatedCancellation.cancelSurveyResult;
33
+ return {
34
+ initiator: "user",
35
+ reason: survey?.reason ?? null,
36
+ feedback: survey?.reason && SURVEY_FEEDBACK[survey.reason] || null,
37
+ comment: survey?.reasonUserInput ?? null
38
+ };
39
+ }
40
+ if (context.systemInitiatedCancellation) return {
41
+ initiator: "system",
42
+ reason: "SYSTEM_INITIATED",
43
+ feedback: null,
44
+ comment: null
45
+ };
46
+ if (context.developerInitiatedCancellation) return {
47
+ initiator: "developer",
48
+ reason: "DEVELOPER_INITIATED",
49
+ feedback: null,
50
+ comment: null
51
+ };
52
+ return null;
53
+ }
54
+ /**
55
+ * When the subscription was cancelled. Only a user cancellation carries the time; for the others
56
+ * the caller falls back to when it learnt of it.
57
+ */
58
+ function mapCanceledAt(context) {
59
+ return context?.userInitiatedCancellation?.cancelTime ?? null;
60
+ }
15
61
  //#endregion
16
- export { mapSubscriptionStatus };
62
+ export { mapCanceledAt, mapCancellationDetails, mapSubscriptionStatus };
17
63
 
18
64
  //# sourceMappingURL=mapper.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"mapper.mjs","names":[],"sources":["../../src/google-play/mapper.ts"],"sourcesContent":["import type { SubscriptionStatus } from '../subscription/index';\nimport type { GooglePlaySubscriptionState } from './real-time-developer-notification';\n\nexport function mapSubscriptionStatus(state: GooglePlaySubscriptionState): SubscriptionStatus {\n switch (state) {\n case 'SUBSCRIPTION_STATE_PENDING':\n return 'PENDING';\n case 'SUBSCRIPTION_STATE_ACTIVE':\n return 'ACTIVE';\n case 'SUBSCRIPTION_STATE_PAUSED':\n return 'PAUSED';\n case 'SUBSCRIPTION_STATE_IN_GRACE_PERIOD':\n return 'IN_GRACE_PERIOD';\n case 'SUBSCRIPTION_STATE_ON_HOLD':\n return 'ON_HOLD';\n case 'SUBSCRIPTION_STATE_CANCELED':\n return 'CANCELED';\n case 'SUBSCRIPTION_STATE_EXPIRED':\n return 'EXPIRED';\n case 'SUBSCRIPTION_STATE_PENDING_PURCHASE_CANCELED':\n return 'PENDING_PURCHASE_CANCELED';\n default:\n throw new Error(`Unknown Google Play subscription state: ${state}`);\n }\n}\n"],"mappings":";AAGA,SAAgB,sBAAsB,OAAwD;CAC5F,QAAQ,OAAR;EACE,KAAK,8BACH,OAAO;EACT,KAAK,6BACH,OAAO;EACT,KAAK,6BACH,OAAO;EACT,KAAK,sCACH,OAAO;EACT,KAAK,8BACH,OAAO;EACT,KAAK,+BACH,OAAO;EACT,KAAK,8BACH,OAAO;EACT,KAAK,gDACH,OAAO;EACT,SACE,MAAM,IAAI,MAAM,2CAA2C,OAAO;CACtE;AACF"}
1
+ {"version":3,"file":"mapper.mjs","names":[],"sources":["../../src/google-play/mapper.ts"],"sourcesContent":["import type { CancellationDetails, SubscriptionStatus } from '../subscription/index';\nimport type { GooglePlaySubscriptionState } from './real-time-developer-notification';\n\nexport function mapSubscriptionStatus(state: GooglePlaySubscriptionState): SubscriptionStatus {\n switch (state) {\n case 'SUBSCRIPTION_STATE_PENDING':\n return 'PENDING';\n case 'SUBSCRIPTION_STATE_ACTIVE':\n return 'ACTIVE';\n case 'SUBSCRIPTION_STATE_PAUSED':\n return 'PAUSED';\n case 'SUBSCRIPTION_STATE_IN_GRACE_PERIOD':\n return 'IN_GRACE_PERIOD';\n case 'SUBSCRIPTION_STATE_ON_HOLD':\n return 'ON_HOLD';\n case 'SUBSCRIPTION_STATE_CANCELED':\n return 'CANCELED';\n case 'SUBSCRIPTION_STATE_EXPIRED':\n return 'EXPIRED';\n case 'SUBSCRIPTION_STATE_PENDING_PURCHASE_CANCELED':\n return 'PENDING_PURCHASE_CANCELED';\n default:\n throw new Error(`Unknown Google Play subscription state: ${state}`);\n }\n}\n\n/** Play's cancel-survey answers in the shared vocabulary. */\nconst SURVEY_FEEDBACK: Record<string, CancellationDetails['feedback']> = {\n CANCEL_SURVEY_REASON_NOT_ENOUGH_USAGE: 'unused',\n CANCEL_SURVEY_REASON_TECHNICAL_ISSUES: 'low_quality',\n CANCEL_SURVEY_REASON_COST_RELATED: 'too_expensive',\n CANCEL_SURVEY_REASON_FOUND_BETTER_APP: 'switched_service',\n CANCEL_SURVEY_REASON_OTHERS: 'other',\n};\n\n/**\n * `canceledStateContext` of `purchases.subscriptionsv2.get`, declared structurally so this\n * module does not depend on the Play Developer API client.\n */\nexport interface CanceledStateContext {\n userInitiatedCancellation?: {\n cancelTime?: string | null;\n cancelSurveyResult?: { reason?: string | null; reasonUserInput?: string | null } | null;\n } | null;\n systemInitiatedCancellation?: object | null;\n developerInitiatedCancellation?: object | null;\n replacementCancellation?: object | null;\n}\n\n/**\n * Why a Play subscription stopped renewing. The Play Store asks the user for a reason on cancel\n * (and for free text when it is \"Other\"), which comes back in `cancelSurveyResult`. Null while\n * the subscription renews, and for a replacement: that is the linked purchase taking over, not a\n * cancellation to report.\n */\nexport function mapCancellationDetails(\n context: CanceledStateContext | null | undefined\n): CancellationDetails | null {\n if (!context) return null;\n if (context.userInitiatedCancellation) {\n const survey = context.userInitiatedCancellation.cancelSurveyResult;\n return {\n initiator: 'user',\n reason: survey?.reason ?? null,\n feedback: (survey?.reason && SURVEY_FEEDBACK[survey.reason]) || null,\n comment: survey?.reasonUserInput ?? null,\n };\n }\n if (context.systemInitiatedCancellation) {\n return { initiator: 'system', reason: 'SYSTEM_INITIATED', feedback: null, comment: null };\n }\n if (context.developerInitiatedCancellation) {\n return { initiator: 'developer', reason: 'DEVELOPER_INITIATED', feedback: null, comment: null };\n }\n return null;\n}\n\n/**\n * When the subscription was cancelled. Only a user cancellation carries the time; for the others\n * the caller falls back to when it learnt of it.\n */\nexport function mapCanceledAt(context: CanceledStateContext | null | undefined): string | null {\n return context?.userInitiatedCancellation?.cancelTime ?? null;\n}\n"],"mappings":";AAGA,SAAgB,sBAAsB,OAAwD;CAC5F,QAAQ,OAAR;EACE,KAAK,8BACH,OAAO;EACT,KAAK,6BACH,OAAO;EACT,KAAK,6BACH,OAAO;EACT,KAAK,sCACH,OAAO;EACT,KAAK,8BACH,OAAO;EACT,KAAK,+BACH,OAAO;EACT,KAAK,8BACH,OAAO;EACT,KAAK,gDACH,OAAO;EACT,SACE,MAAM,IAAI,MAAM,2CAA2C,OAAO;CACtE;AACF;;AAGA,MAAM,kBAAmE;CACvE,uCAAuC;CACvC,uCAAuC;CACvC,mCAAmC;CACnC,uCAAuC;CACvC,6BAA6B;AAC/B;;;;;;;AAsBA,SAAgB,uBACd,SAC4B;CAC5B,IAAI,CAAC,SAAS,OAAO;CACrB,IAAI,QAAQ,2BAA2B;EACrC,MAAM,SAAS,QAAQ,0BAA0B;EACjD,OAAO;GACL,WAAW;GACX,QAAQ,QAAQ,UAAU;GAC1B,UAAW,QAAQ,UAAU,gBAAgB,OAAO,WAAY;GAChE,SAAS,QAAQ,mBAAmB;EACtC;CACF;CACA,IAAI,QAAQ,6BACV,OAAO;EAAE,WAAW;EAAU,QAAQ;EAAoB,UAAU;EAAM,SAAS;CAAK;CAE1F,IAAI,QAAQ,gCACV,OAAO;EAAE,WAAW;EAAa,QAAQ;EAAuB,UAAU;EAAM,SAAS;CAAK;CAEhG,OAAO;AACT;;;;;AAMA,SAAgB,cAAc,SAAiE;CAC7F,OAAO,SAAS,2BAA2B,cAAc;AAC3D"}
package/dist/index.cjs CHANGED
@@ -5,7 +5,10 @@ const require_google_play_config = require("./google-play/config.cjs");
5
5
  const require_stripe_config = require("./stripe/config.cjs");
6
6
  exports.AVAILABLE_STATUSES = require_subscription_index.AVAILABLE_STATUSES;
7
7
  exports.AppStoreConfig = require_app_store_config.AppStoreConfig;
8
+ exports.CANCELLATION_FEEDBACKS = require_subscription_index.CANCELLATION_FEEDBACKS;
9
+ exports.CANCELLATION_INITIATORS = require_subscription_index.CANCELLATION_INITIATORS;
8
10
  exports.GooglePlayConfig = require_google_play_config.GooglePlayConfig;
9
11
  exports.PLATFORMS = require_subscription_index.PLATFORMS;
12
+ exports.RESUBSCRIBE_INTENTS = require_subscription_index.RESUBSCRIBE_INTENTS;
10
13
  exports.SUBSCRIPTION_STATUSES = require_subscription_index.SUBSCRIPTION_STATUSES;
11
14
  exports.StripeConfig = require_stripe_config.StripeConfig;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AppStoreConfig } from "./app-store/config.cjs";
2
+ import { AVAILABLE_STATUSES, CANCELLATION_FEEDBACKS, CANCELLATION_INITIATORS, CancellationDetails, CancellationFeedback, CancellationInitiator, PLATFORMS, Platform, RESUBSCRIBE_INTENTS, ResubscribeIntent, SUBSCRIPTION_STATUSES, SubscriptionStatus } from "./subscription/index.cjs";
2
3
  import { GooglePlayConfig } from "./google-play/config.cjs";
3
- import { AVAILABLE_STATUSES, PLATFORMS, Platform, SUBSCRIPTION_STATUSES, SubscriptionStatus } from "./subscription/index.cjs";
4
4
  import { StripeConfig } from "./stripe/config.cjs";
5
- export { AVAILABLE_STATUSES, AppStoreConfig, GooglePlayConfig, PLATFORMS, type Platform, SUBSCRIPTION_STATUSES, StripeConfig, type SubscriptionStatus };
5
+ export { AVAILABLE_STATUSES, AppStoreConfig, CANCELLATION_FEEDBACKS, CANCELLATION_INITIATORS, type CancellationDetails, type CancellationFeedback, type CancellationInitiator, GooglePlayConfig, PLATFORMS, type Platform, RESUBSCRIBE_INTENTS, type ResubscribeIntent, SUBSCRIPTION_STATUSES, StripeConfig, type SubscriptionStatus };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AppStoreConfig } from "./app-store/config.mjs";
2
+ import { AVAILABLE_STATUSES, CANCELLATION_FEEDBACKS, CANCELLATION_INITIATORS, CancellationDetails, CancellationFeedback, CancellationInitiator, PLATFORMS, Platform, RESUBSCRIBE_INTENTS, ResubscribeIntent, SUBSCRIPTION_STATUSES, SubscriptionStatus } from "./subscription/index.mjs";
2
3
  import { GooglePlayConfig } from "./google-play/config.mjs";
3
- import { AVAILABLE_STATUSES, PLATFORMS, Platform, SUBSCRIPTION_STATUSES, SubscriptionStatus } from "./subscription/index.mjs";
4
4
  import { StripeConfig } from "./stripe/config.mjs";
5
- export { AVAILABLE_STATUSES, AppStoreConfig, GooglePlayConfig, PLATFORMS, type Platform, SUBSCRIPTION_STATUSES, StripeConfig, type SubscriptionStatus };
5
+ export { AVAILABLE_STATUSES, AppStoreConfig, CANCELLATION_FEEDBACKS, CANCELLATION_INITIATORS, type CancellationDetails, type CancellationFeedback, type CancellationInitiator, GooglePlayConfig, PLATFORMS, type Platform, RESUBSCRIBE_INTENTS, type ResubscribeIntent, SUBSCRIPTION_STATUSES, StripeConfig, type SubscriptionStatus };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { AVAILABLE_STATUSES, PLATFORMS, SUBSCRIPTION_STATUSES } from "./subscription/index.mjs";
1
+ import { AVAILABLE_STATUSES, CANCELLATION_FEEDBACKS, CANCELLATION_INITIATORS, PLATFORMS, RESUBSCRIBE_INTENTS, SUBSCRIPTION_STATUSES } from "./subscription/index.mjs";
2
2
  import { AppStoreConfig } from "./app-store/config.mjs";
3
3
  import { GooglePlayConfig } from "./google-play/config.mjs";
4
4
  import { StripeConfig } from "./stripe/config.mjs";
5
- export { AVAILABLE_STATUSES, AppStoreConfig, GooglePlayConfig, PLATFORMS, SUBSCRIPTION_STATUSES, StripeConfig };
5
+ export { AVAILABLE_STATUSES, AppStoreConfig, CANCELLATION_FEEDBACKS, CANCELLATION_INITIATORS, GooglePlayConfig, PLATFORMS, RESUBSCRIBE_INTENTS, SUBSCRIPTION_STATUSES, StripeConfig };
@@ -14,6 +14,7 @@ exports.createCheckoutSessionSchema = require_stripe_schema.createCheckoutSessio
14
14
  exports.getBeginCheckoutProperties = require_stripe_mapper.getBeginCheckoutProperties;
15
15
  exports.getPendingCheckouts = require_stripe_pending_checkout.getPendingCheckouts;
16
16
  exports.getPurchaseProperties = require_stripe_mapper.getPurchaseProperties;
17
+ exports.mapCancellationDetails = require_stripe_mapper.mapCancellationDetails;
17
18
  exports.mapCharge = require_stripe_mapper.mapCharge;
18
19
  exports.mapCheckoutSession = require_stripe_mapper.mapCheckoutSession;
19
20
  exports.mapInvoice = require_stripe_mapper.mapInvoice;
@@ -1,8 +1,9 @@
1
+ import { CancellationDetails } from "../subscription/index.cjs";
1
2
  import { PriceId, StripeConfig, StripeMode } from "./config.cjs";
2
3
  import { StripeEventHandler } from "./handler.cjs";
3
- import { BeginCheckoutProperties, CheckoutSession, LineItem, PaymentStatus, Price, ProductPrice, PurchaseProperties, getBeginCheckoutProperties, getPurchaseProperties, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price } from "./mapper.cjs";
4
- import { CancellationDetails, CreateCheckoutSessionDTO, cancellationDetailsSchema, createCheckoutSessionSchema } from "./schema.cjs";
4
+ import { BeginCheckoutProperties, CheckoutSession, LineItem, PaymentStatus, Price, ProductPrice, PurchaseProperties, getBeginCheckoutProperties, getPurchaseProperties, mapCancellationDetails, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price } from "./mapper.cjs";
5
+ import { CreateCheckoutSessionDTO, cancellationDetailsSchema, createCheckoutSessionSchema } from "./schema.cjs";
5
6
  import { METADATA_KEYS } from "./metadata.cjs";
6
7
  import { addPendingCheckout, getPendingCheckouts, removePendingCheckout } from "./pending-checkout.cjs";
7
8
  import { Stripe } from "stripe";
8
- export { type BeginCheckoutProperties, type CancellationDetails, type CheckoutSession, type CreateCheckoutSessionDTO, type LineItem, METADATA_KEYS, type PaymentStatus, type Price, type PriceId, type ProductPrice, type PurchaseProperties, type Stripe, StripeConfig, StripeEventHandler, type StripeMode, addPendingCheckout, cancellationDetailsSchema, createCheckoutSessionSchema, getBeginCheckoutProperties, getPendingCheckouts, getPurchaseProperties, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price, removePendingCheckout };
9
+ export { type BeginCheckoutProperties, type CancellationDetails, type CheckoutSession, type CreateCheckoutSessionDTO, type LineItem, METADATA_KEYS, type PaymentStatus, type Price, type PriceId, type ProductPrice, type PurchaseProperties, type Stripe, StripeConfig, StripeEventHandler, type StripeMode, addPendingCheckout, cancellationDetailsSchema, createCheckoutSessionSchema, getBeginCheckoutProperties, getPendingCheckouts, getPurchaseProperties, mapCancellationDetails, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price, removePendingCheckout };
@@ -1,8 +1,9 @@
1
+ import { CancellationDetails } from "../subscription/index.mjs";
1
2
  import { PriceId, StripeConfig, StripeMode } from "./config.mjs";
2
3
  import { StripeEventHandler } from "./handler.mjs";
3
- import { BeginCheckoutProperties, CheckoutSession, LineItem, PaymentStatus, Price, ProductPrice, PurchaseProperties, getBeginCheckoutProperties, getPurchaseProperties, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price } from "./mapper.mjs";
4
- import { CancellationDetails, CreateCheckoutSessionDTO, cancellationDetailsSchema, createCheckoutSessionSchema } from "./schema.mjs";
4
+ import { BeginCheckoutProperties, CheckoutSession, LineItem, PaymentStatus, Price, ProductPrice, PurchaseProperties, getBeginCheckoutProperties, getPurchaseProperties, mapCancellationDetails, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price } from "./mapper.mjs";
5
+ import { CreateCheckoutSessionDTO, cancellationDetailsSchema, createCheckoutSessionSchema } from "./schema.mjs";
5
6
  import { METADATA_KEYS } from "./metadata.mjs";
6
7
  import { addPendingCheckout, getPendingCheckouts, removePendingCheckout } from "./pending-checkout.mjs";
7
8
  import { Stripe } from "stripe";
8
- export { type BeginCheckoutProperties, type CancellationDetails, type CheckoutSession, type CreateCheckoutSessionDTO, type LineItem, METADATA_KEYS, type PaymentStatus, type Price, type PriceId, type ProductPrice, type PurchaseProperties, type Stripe, StripeConfig, StripeEventHandler, type StripeMode, addPendingCheckout, cancellationDetailsSchema, createCheckoutSessionSchema, getBeginCheckoutProperties, getPendingCheckouts, getPurchaseProperties, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price, removePendingCheckout };
9
+ export { type BeginCheckoutProperties, type CancellationDetails, type CheckoutSession, type CreateCheckoutSessionDTO, type LineItem, METADATA_KEYS, type PaymentStatus, type Price, type PriceId, type ProductPrice, type PurchaseProperties, type Stripe, StripeConfig, StripeEventHandler, type StripeMode, addPendingCheckout, cancellationDetailsSchema, createCheckoutSessionSchema, getBeginCheckoutProperties, getPendingCheckouts, getPurchaseProperties, mapCancellationDetails, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price, removePendingCheckout };
@@ -1,7 +1,7 @@
1
1
  import { StripeConfig } from "./config.mjs";
2
2
  import { StripeEventHandler } from "./handler.mjs";
3
- import { getBeginCheckoutProperties, getPurchaseProperties, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price } from "./mapper.mjs";
3
+ import { getBeginCheckoutProperties, getPurchaseProperties, mapCancellationDetails, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price } from "./mapper.mjs";
4
4
  import { cancellationDetailsSchema, createCheckoutSessionSchema } from "./schema.mjs";
5
5
  import { METADATA_KEYS } from "./metadata.mjs";
6
6
  import { addPendingCheckout, getPendingCheckouts, removePendingCheckout } from "./pending-checkout.mjs";
7
- export { METADATA_KEYS, StripeConfig, StripeEventHandler, addPendingCheckout, cancellationDetailsSchema, createCheckoutSessionSchema, getBeginCheckoutProperties, getPendingCheckouts, getPurchaseProperties, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price, removePendingCheckout };
7
+ export { METADATA_KEYS, StripeConfig, StripeEventHandler, addPendingCheckout, cancellationDetailsSchema, createCheckoutSessionSchema, getBeginCheckoutProperties, getPendingCheckouts, getPurchaseProperties, mapCancellationDetails, mapCharge, mapCheckoutSession, mapInvoice, mapLineItem, mapPaymentIntent, mapPrice, mapSubscriptionStatus, mapTime, minorUnits, price, removePendingCheckout };
@@ -1,4 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_subscription_index = require("../subscription/index.cjs");
2
3
  //#region src/stripe/mapper.ts
3
4
  function mapTime(stripeTimestampSeconds) {
4
5
  if (!stripeTimestampSeconds) return null;
@@ -198,10 +199,27 @@ function getBeginCheckoutProperties(p) {
198
199
  }]
199
200
  };
200
201
  }
202
+ /**
203
+ * Stripe's `cancellation_details` in the shared shape. The object is present on every
204
+ * subscription with all three fields null, so an active one maps to null rather than an empty
205
+ * record. `reason` says who acted: `cancellation_requested` is the customer (or us on their
206
+ * behalf), the payment reasons are Stripe ending it.
207
+ */
208
+ function mapCancellationDetails(subscription) {
209
+ const details = subscription.cancellation_details;
210
+ if (!details || !details.reason && !details.feedback && !details.comment) return null;
211
+ return {
212
+ initiator: details.reason === "payment_failed" || details.reason === "payment_disputed" ? "system" : "user",
213
+ reason: details.reason ?? null,
214
+ feedback: details.feedback ? require_subscription_index.CANCELLATION_FEEDBACKS.includes(details.feedback) ? details.feedback : "other" : null,
215
+ comment: details.comment ?? null
216
+ };
217
+ }
201
218
  //#endregion
202
219
  exports.ZERO_DECIMAL_CURRENCIES = ZERO_DECIMAL_CURRENCIES;
203
220
  exports.getBeginCheckoutProperties = getBeginCheckoutProperties;
204
221
  exports.getPurchaseProperties = getPurchaseProperties;
222
+ exports.mapCancellationDetails = mapCancellationDetails;
205
223
  exports.mapCharge = mapCharge;
206
224
  exports.mapCheckoutSession = mapCheckoutSession;
207
225
  exports.mapInvoice = mapInvoice;