@reorderjs/reorder 1.0.1

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 (231) hide show
  1. package/.medusa/server/scripts/reset-reorder-plugin-data.js +175 -0
  2. package/.medusa/server/src/admin/index.js +17889 -0
  3. package/.medusa/server/src/admin/index.mjs +17871 -0
  4. package/.medusa/server/src/admin/types/activity-log.js +10 -0
  5. package/.medusa/server/src/admin/types/analytics.js +17 -0
  6. package/.medusa/server/src/admin/types/cancellation.js +27 -0
  7. package/.medusa/server/src/admin/types/dunning.js +19 -0
  8. package/.medusa/server/src/admin/types/plan-offer.js +25 -0
  9. package/.medusa/server/src/admin/types/renewal.js +23 -0
  10. package/.medusa/server/src/admin/types/subscription.js +22 -0
  11. package/.medusa/server/src/api/admin/cancellations/[id]/apply-offer/route.js +30 -0
  12. package/.medusa/server/src/api/admin/cancellations/[id]/finalize/route.js +31 -0
  13. package/.medusa/server/src/api/admin/cancellations/[id]/reason/route.js +31 -0
  14. package/.medusa/server/src/api/admin/cancellations/[id]/route.js +20 -0
  15. package/.medusa/server/src/api/admin/cancellations/middlewares.js +55 -0
  16. package/.medusa/server/src/api/admin/cancellations/route.js +20 -0
  17. package/.medusa/server/src/api/admin/cancellations/utils.js +116 -0
  18. package/.medusa/server/src/api/admin/cancellations/validators.js +130 -0
  19. package/.medusa/server/src/api/admin/dunning/[id]/mark-recovered/route.js +27 -0
  20. package/.medusa/server/src/api/admin/dunning/[id]/mark-unrecovered/route.js +27 -0
  21. package/.medusa/server/src/api/admin/dunning/[id]/retry-now/route.js +28 -0
  22. package/.medusa/server/src/api/admin/dunning/[id]/retry-schedule/route.js +29 -0
  23. package/.medusa/server/src/api/admin/dunning/[id]/route.js +20 -0
  24. package/.medusa/server/src/api/admin/dunning/middlewares.js +60 -0
  25. package/.medusa/server/src/api/admin/dunning/route.js +20 -0
  26. package/.medusa/server/src/api/admin/dunning/utils.js +70 -0
  27. package/.medusa/server/src/api/admin/dunning/validators.js +81 -0
  28. package/.medusa/server/src/api/admin/orders/[id]/subscription-summary/route.js +10 -0
  29. package/.medusa/server/src/api/admin/orders/utils.js +8 -0
  30. package/.medusa/server/src/api/admin/plugin/route.js +7 -0
  31. package/.medusa/server/src/api/admin/renewals/[id]/approve-changes/route.js +27 -0
  32. package/.medusa/server/src/api/admin/renewals/[id]/force/route.js +30 -0
  33. package/.medusa/server/src/api/admin/renewals/[id]/reject-changes/route.js +27 -0
  34. package/.medusa/server/src/api/admin/renewals/[id]/route.js +10 -0
  35. package/.medusa/server/src/api/admin/renewals/middlewares.js +61 -0
  36. package/.medusa/server/src/api/admin/renewals/route.js +10 -0
  37. package/.medusa/server/src/api/admin/renewals/utils.js +60 -0
  38. package/.medusa/server/src/api/admin/renewals/validators.js +62 -0
  39. package/.medusa/server/src/api/admin/subscription-analytics/export/route.js +20 -0
  40. package/.medusa/server/src/api/admin/subscription-analytics/kpis/route.js +20 -0
  41. package/.medusa/server/src/api/admin/subscription-analytics/middlewares.js +45 -0
  42. package/.medusa/server/src/api/admin/subscription-analytics/rebuild/route.js +75 -0
  43. package/.medusa/server/src/api/admin/subscription-analytics/trends/route.js +20 -0
  44. package/.medusa/server/src/api/admin/subscription-analytics/utils.js +81 -0
  45. package/.medusa/server/src/api/admin/subscription-analytics/validators.js +76 -0
  46. package/.medusa/server/src/api/admin/subscription-logs/[id]/route.js +20 -0
  47. package/.medusa/server/src/api/admin/subscription-logs/middlewares.js +66 -0
  48. package/.medusa/server/src/api/admin/subscription-logs/route.js +20 -0
  49. package/.medusa/server/src/api/admin/subscription-logs/utils.js +84 -0
  50. package/.medusa/server/src/api/admin/subscription-logs/validators.js +32 -0
  51. package/.medusa/server/src/api/admin/subscription-offers/[id]/route.js +22 -0
  52. package/.medusa/server/src/api/admin/subscription-offers/[id]/toggle/route.js +17 -0
  53. package/.medusa/server/src/api/admin/subscription-offers/middlewares.js +58 -0
  54. package/.medusa/server/src/api/admin/subscription-offers/route.js +20 -0
  55. package/.medusa/server/src/api/admin/subscription-offers/utils.js +41 -0
  56. package/.medusa/server/src/api/admin/subscription-offers/validators.js +112 -0
  57. package/.medusa/server/src/api/admin/subscription-settings/middlewares.js +15 -0
  58. package/.medusa/server/src/api/admin/subscription-settings/route.js +33 -0
  59. package/.medusa/server/src/api/admin/subscription-settings/utils.js +109 -0
  60. package/.medusa/server/src/api/admin/subscription-settings/validators.js +74 -0
  61. package/.medusa/server/src/api/admin/subscriptions/[id]/cancel/route.js +18 -0
  62. package/.medusa/server/src/api/admin/subscriptions/[id]/logs/route.js +20 -0
  63. package/.medusa/server/src/api/admin/subscriptions/[id]/pause/route.js +18 -0
  64. package/.medusa/server/src/api/admin/subscriptions/[id]/resume/route.js +18 -0
  65. package/.medusa/server/src/api/admin/subscriptions/[id]/route.js +10 -0
  66. package/.medusa/server/src/api/admin/subscriptions/[id]/schedule-plan-change/route.js +26 -0
  67. package/.medusa/server/src/api/admin/subscriptions/[id]/update-shipping-address/route.js +27 -0
  68. package/.medusa/server/src/api/admin/subscriptions/middlewares.js +79 -0
  69. package/.medusa/server/src/api/admin/subscriptions/route.js +10 -0
  70. package/.medusa/server/src/api/admin/subscriptions/utils.js +42 -0
  71. package/.medusa/server/src/api/admin/subscriptions/validators.js +76 -0
  72. package/.medusa/server/src/api/middlewares.js +32 -0
  73. package/.medusa/server/src/api/store/carts/[id]/subscribe/route.js +18 -0
  74. package/.medusa/server/src/api/store/customers/me/subscriptions/[id]/cancellation/route.js +37 -0
  75. package/.medusa/server/src/api/store/customers/me/subscriptions/route.js +10 -0
  76. package/.medusa/server/src/api/store/customers/me/subscriptions/utils.js +104 -0
  77. package/.medusa/server/src/api/store/customers/me/subscriptions/validators.js +13 -0
  78. package/.medusa/server/src/api/store/plugin/route.js +7 -0
  79. package/.medusa/server/src/jobs/process-analytics-daily-snapshots.js +149 -0
  80. package/.medusa/server/src/jobs/process-cancellation-operational-metrics.js +102 -0
  81. package/.medusa/server/src/jobs/process-dunning-retries.js +249 -0
  82. package/.medusa/server/src/jobs/process-renewal-cycles.js +180 -0
  83. package/.medusa/server/src/links/cancellation-subscription.js +13 -0
  84. package/.medusa/server/src/links/renewal-order.js +12 -0
  85. package/.medusa/server/src/links/renewal-subscription.js +13 -0
  86. package/.medusa/server/src/links/subscription-cart.js +12 -0
  87. package/.medusa/server/src/links/subscription-customer.js +13 -0
  88. package/.medusa/server/src/links/subscription-order.js +13 -0
  89. package/.medusa/server/src/links/subscription-product.js +13 -0
  90. package/.medusa/server/src/links/subscription-variant.js +13 -0
  91. package/.medusa/server/src/modules/activity-log/index.js +13 -0
  92. package/.medusa/server/src/modules/activity-log/migrations/Migration20260401204521.js +24 -0
  93. package/.medusa/server/src/modules/activity-log/migrations/Migration20260405112500.js +16 -0
  94. package/.medusa/server/src/modules/activity-log/models/subscription-log.js +52 -0
  95. package/.medusa/server/src/modules/activity-log/service.js +13 -0
  96. package/.medusa/server/src/modules/activity-log/types/index.js +33 -0
  97. package/.medusa/server/src/modules/activity-log/utils/admin-query.js +261 -0
  98. package/.medusa/server/src/modules/activity-log/utils/normalize-log-event.js +169 -0
  99. package/.medusa/server/src/modules/analytics/constants.js +8 -0
  100. package/.medusa/server/src/modules/analytics/index.js +13 -0
  101. package/.medusa/server/src/modules/analytics/migrations/Migration20260402183116.js +27 -0
  102. package/.medusa/server/src/modules/analytics/models/subscription-metrics-daily.js +65 -0
  103. package/.medusa/server/src/modules/analytics/service.js +13 -0
  104. package/.medusa/server/src/modules/analytics/utils/admin-query.js +632 -0
  105. package/.medusa/server/src/modules/analytics/utils/data-quality.js +101 -0
  106. package/.medusa/server/src/modules/analytics/utils/observability.js +127 -0
  107. package/.medusa/server/src/modules/cancellation/index.js +13 -0
  108. package/.medusa/server/src/modules/cancellation/migrations/Migration20260401143914.js +34 -0
  109. package/.medusa/server/src/modules/cancellation/migrations/Migration20260405112000.js +14 -0
  110. package/.medusa/server/src/modules/cancellation/models/cancellation-case.js +52 -0
  111. package/.medusa/server/src/modules/cancellation/models/retention-offer-event.js +47 -0
  112. package/.medusa/server/src/modules/cancellation/service.js +15 -0
  113. package/.medusa/server/src/modules/cancellation/types/index.js +43 -0
  114. package/.medusa/server/src/modules/cancellation/utils/admin-query.js +530 -0
  115. package/.medusa/server/src/modules/cancellation/utils/audit.js +21 -0
  116. package/.medusa/server/src/modules/cancellation/utils/errors.js +31 -0
  117. package/.medusa/server/src/modules/cancellation/utils/observability.js +77 -0
  118. package/.medusa/server/src/modules/cancellation/utils/operational-metrics.js +131 -0
  119. package/.medusa/server/src/modules/cancellation/utils/retention-offer-policy.js +31 -0
  120. package/.medusa/server/src/modules/dunning/index.js +13 -0
  121. package/.medusa/server/src/modules/dunning/migrations/Migration20260330190157.js +36 -0
  122. package/.medusa/server/src/modules/dunning/models/dunning-attempt.js +48 -0
  123. package/.medusa/server/src/modules/dunning/models/dunning-case.js +61 -0
  124. package/.medusa/server/src/modules/dunning/service.js +15 -0
  125. package/.medusa/server/src/modules/dunning/types/index.js +19 -0
  126. package/.medusa/server/src/modules/dunning/utils/admin-query.js +548 -0
  127. package/.medusa/server/src/modules/dunning/utils/errors.js +40 -0
  128. package/.medusa/server/src/modules/dunning/utils/observability.js +109 -0
  129. package/.medusa/server/src/modules/dunning/utils/retry-schedule.js +47 -0
  130. package/.medusa/server/src/modules/dunning/utils/scheduler-query.js +42 -0
  131. package/.medusa/server/src/modules/plan-offer/index.js +13 -0
  132. package/.medusa/server/src/modules/plan-offer/migrations/Migration20260329104245.js +22 -0
  133. package/.medusa/server/src/modules/plan-offer/migrations/Migration20260329153000.js +25 -0
  134. package/.medusa/server/src/modules/plan-offer/models/plan-offer.js +35 -0
  135. package/.medusa/server/src/modules/plan-offer/service.js +13 -0
  136. package/.medusa/server/src/modules/plan-offer/types/index.js +26 -0
  137. package/.medusa/server/src/modules/plan-offer/utils/admin-query.js +429 -0
  138. package/.medusa/server/src/modules/plan-offer/utils/effective-config.js +84 -0
  139. package/.medusa/server/src/modules/plan-offer/utils/errors.js +55 -0
  140. package/.medusa/server/src/modules/renewal/index.js +13 -0
  141. package/.medusa/server/src/modules/renewal/migrations/Migration20260329185930.js +34 -0
  142. package/.medusa/server/src/modules/renewal/models/renewal-attempt.js +49 -0
  143. package/.medusa/server/src/modules/renewal/models/renewal-cycle.js +56 -0
  144. package/.medusa/server/src/modules/renewal/service.js +15 -0
  145. package/.medusa/server/src/modules/renewal/types/index.js +23 -0
  146. package/.medusa/server/src/modules/renewal/utils/admin-query.js +450 -0
  147. package/.medusa/server/src/modules/renewal/utils/errors.js +39 -0
  148. package/.medusa/server/src/modules/renewal/utils/observability.js +89 -0
  149. package/.medusa/server/src/modules/renewal/utils/scheduler-query.js +48 -0
  150. package/.medusa/server/src/modules/renewal/utils/upcoming-cycle.js +54 -0
  151. package/.medusa/server/src/modules/settings/index.js +13 -0
  152. package/.medusa/server/src/modules/settings/migrations/Migration20260403121004.js +17 -0
  153. package/.medusa/server/src/modules/settings/migrations/Migration20260403132519.js +17 -0
  154. package/.medusa/server/src/modules/settings/models/subscription-settings.js +32 -0
  155. package/.medusa/server/src/modules/settings/service.js +82 -0
  156. package/.medusa/server/src/modules/settings/types.js +15 -0
  157. package/.medusa/server/src/modules/settings/utils/audit.js +43 -0
  158. package/.medusa/server/src/modules/settings/utils/normalize-settings.js +99 -0
  159. package/.medusa/server/src/modules/subscription/index.js +13 -0
  160. package/.medusa/server/src/modules/subscription/migrations/Migration20260327143452.js +24 -0
  161. package/.medusa/server/src/modules/subscription/migrations/Migration20260329194835.js +16 -0
  162. package/.medusa/server/src/modules/subscription/models/subscription.js +64 -0
  163. package/.medusa/server/src/modules/subscription/service.js +13 -0
  164. package/.medusa/server/src/modules/subscription/types/index.js +17 -0
  165. package/.medusa/server/src/modules/subscription/utils/admin-query.js +465 -0
  166. package/.medusa/server/src/modules/subscription/utils/errors.js +28 -0
  167. package/.medusa/server/src/subscription-flows/create-subscription-from-cart.js +178 -0
  168. package/.medusa/server/src/workflows/apply-retention-offer.js +52 -0
  169. package/.medusa/server/src/workflows/approve-renewal-changes.js +61 -0
  170. package/.medusa/server/src/workflows/cancel-subscription.js +64 -0
  171. package/.medusa/server/src/workflows/create-or-upsert-plan-offer.js +11 -0
  172. package/.medusa/server/src/workflows/ensure-next-renewal-cycle.js +11 -0
  173. package/.medusa/server/src/workflows/finalize-cancellation.js +88 -0
  174. package/.medusa/server/src/workflows/force-renewal-cycle.js +11 -0
  175. package/.medusa/server/src/workflows/index.js +79 -0
  176. package/.medusa/server/src/workflows/mark-dunning-recovered.js +11 -0
  177. package/.medusa/server/src/workflows/mark-dunning-unrecovered.js +11 -0
  178. package/.medusa/server/src/workflows/pause-subscription.js +61 -0
  179. package/.medusa/server/src/workflows/process-renewal-cycle.js +43 -0
  180. package/.medusa/server/src/workflows/rebuild-analytics-daily-snapshots.js +13 -0
  181. package/.medusa/server/src/workflows/reject-renewal-changes.js +61 -0
  182. package/.medusa/server/src/workflows/resume-subscription.js +76 -0
  183. package/.medusa/server/src/workflows/run-dunning-retry.js +23 -0
  184. package/.medusa/server/src/workflows/schedule-subscription-plan-change.js +57 -0
  185. package/.medusa/server/src/workflows/start-cancellation-case.js +58 -0
  186. package/.medusa/server/src/workflows/start-dunning.js +11 -0
  187. package/.medusa/server/src/workflows/steps/apply-retention-offer.js +200 -0
  188. package/.medusa/server/src/workflows/steps/approve-renewal-changes.js +48 -0
  189. package/.medusa/server/src/workflows/steps/cancel-subscription.js +48 -0
  190. package/.medusa/server/src/workflows/steps/create-initial-renewal-cycle.js +6 -0
  191. package/.medusa/server/src/workflows/steps/create-subscription-log-event.js +61 -0
  192. package/.medusa/server/src/workflows/steps/create-subscription-record.js +56 -0
  193. package/.medusa/server/src/workflows/steps/ensure-next-renewal-cycle.js +151 -0
  194. package/.medusa/server/src/workflows/steps/finalize-cancellation.js +161 -0
  195. package/.medusa/server/src/workflows/steps/force-renewal-cycle.js +120 -0
  196. package/.medusa/server/src/workflows/steps/link-subscription-commerce-entities.js +44 -0
  197. package/.medusa/server/src/workflows/steps/mark-dunning-recovered.js +72 -0
  198. package/.medusa/server/src/workflows/steps/mark-dunning-unrecovered.js +53 -0
  199. package/.medusa/server/src/workflows/steps/normalize-analytics-rebuild-range.js +59 -0
  200. package/.medusa/server/src/workflows/steps/pause-subscription.js +50 -0
  201. package/.medusa/server/src/workflows/steps/process-renewal-cycle.js +641 -0
  202. package/.medusa/server/src/workflows/steps/rebuild-analytics-daily-snapshots.js +519 -0
  203. package/.medusa/server/src/workflows/steps/reject-renewal-changes.js +48 -0
  204. package/.medusa/server/src/workflows/steps/resume-subscription.js +45 -0
  205. package/.medusa/server/src/workflows/steps/run-dunning-retry.js +592 -0
  206. package/.medusa/server/src/workflows/steps/schedule-subscription-plan-change.js +81 -0
  207. package/.medusa/server/src/workflows/steps/shared-cancellation-log.js +3 -0
  208. package/.medusa/server/src/workflows/steps/shared-plan-offer.js +280 -0
  209. package/.medusa/server/src/workflows/steps/shared-renewal-approval.js +34 -0
  210. package/.medusa/server/src/workflows/steps/start-cancellation-case.js +147 -0
  211. package/.medusa/server/src/workflows/steps/start-dunning.js +237 -0
  212. package/.medusa/server/src/workflows/steps/toggle-plan-offer.js +33 -0
  213. package/.medusa/server/src/workflows/steps/update-cancellation-reason.js +95 -0
  214. package/.medusa/server/src/workflows/steps/update-dunning-retry-schedule.js +91 -0
  215. package/.medusa/server/src/workflows/steps/update-plan-offer.js +51 -0
  216. package/.medusa/server/src/workflows/steps/update-subscription-settings.js +91 -0
  217. package/.medusa/server/src/workflows/steps/update-subscription-shipping-address.js +54 -0
  218. package/.medusa/server/src/workflows/steps/upsert-plan-offer.js +48 -0
  219. package/.medusa/server/src/workflows/steps/validate-subscription-cart.js +280 -0
  220. package/.medusa/server/src/workflows/toggle-plan-offer.js +11 -0
  221. package/.medusa/server/src/workflows/update-cancellation-reason.js +53 -0
  222. package/.medusa/server/src/workflows/update-dunning-retry-schedule.js +11 -0
  223. package/.medusa/server/src/workflows/update-plan-offer.js +11 -0
  224. package/.medusa/server/src/workflows/update-subscription-settings.js +11 -0
  225. package/.medusa/server/src/workflows/update-subscription-shipping-address.js +99 -0
  226. package/.medusa/server/src/workflows/utils/analytics-incremental.js +24 -0
  227. package/.medusa/server/src/workflows/utils/date-output.js +13 -0
  228. package/.medusa/server/src/workflows/utils/subscription-settings.js +13 -0
  229. package/LICENSE +21 -0
  230. package/README.md +200 -0
  231. package/package.json +73 -0
@@ -0,0 +1,632 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAdminAnalyticsKpis = getAdminAnalyticsKpis;
4
+ exports.getAdminAnalyticsTrends = getAdminAnalyticsTrends;
5
+ exports.getAdminAnalyticsExport = getAdminAnalyticsExport;
6
+ const utils_1 = require("@medusajs/framework/utils");
7
+ const utils_2 = require("@medusajs/framework/utils");
8
+ const analytics_1 = require("../../../admin/types/analytics");
9
+ const constants_1 = require("../constants");
10
+ const observability_1 = require("./observability");
11
+ const DEFAULT_LOOKBACK_DAYS = 30;
12
+ const DEFAULT_ANALYTICS_TIMEZONE = "UTC";
13
+ const MAX_ANALYTICS_WINDOW_DAYS = 731;
14
+ const METRIC_LABELS = {
15
+ [analytics_1.AnalyticsMetricKey.MRR]: "MRR",
16
+ [analytics_1.AnalyticsMetricKey.CHURN_RATE]: "Churn Rate",
17
+ [analytics_1.AnalyticsMetricKey.LTV]: "LTV",
18
+ [analytics_1.AnalyticsMetricKey.ACTIVE_SUBSCRIPTIONS_COUNT]: "Active Subscriptions",
19
+ };
20
+ function getQuery(container) {
21
+ return container.resolve(utils_2.ContainerRegistrationKeys.QUERY);
22
+ }
23
+ function getLogger(container) {
24
+ return container.resolve("logger");
25
+ }
26
+ function toUtcDayStart(value) {
27
+ const parsed = value instanceof Date ? new Date(value) : new Date(value);
28
+ return new Date(Date.UTC(parsed.getUTCFullYear(), parsed.getUTCMonth(), parsed.getUTCDate()));
29
+ }
30
+ function toUtcDayEnd(value) {
31
+ const dayStart = toUtcDayStart(value);
32
+ return new Date(Date.UTC(dayStart.getUTCFullYear(), dayStart.getUTCMonth(), dayStart.getUTCDate(), 23, 59, 59, 999));
33
+ }
34
+ function toUtcWeekStart(value) {
35
+ const dayStart = toUtcDayStart(value);
36
+ const utcDay = dayStart.getUTCDay();
37
+ const offset = utcDay === 0 ? -6 : 1 - utcDay;
38
+ const weekStart = new Date(dayStart);
39
+ weekStart.setUTCDate(weekStart.getUTCDate() + offset);
40
+ return weekStart;
41
+ }
42
+ function toUtcWeekEnd(value) {
43
+ const weekStart = toUtcWeekStart(value);
44
+ const weekEnd = new Date(weekStart);
45
+ weekEnd.setUTCDate(weekEnd.getUTCDate() + 6);
46
+ weekEnd.setUTCHours(23, 59, 59, 999);
47
+ return weekEnd;
48
+ }
49
+ function toUtcMonthStart(value) {
50
+ const parsed = value instanceof Date ? value : new Date(value);
51
+ return new Date(Date.UTC(parsed.getUTCFullYear(), parsed.getUTCMonth(), 1));
52
+ }
53
+ function toUtcMonthEnd(value) {
54
+ const monthStart = toUtcMonthStart(value);
55
+ return new Date(Date.UTC(monthStart.getUTCFullYear(), monthStart.getUTCMonth() + 1, 0, 23, 59, 59, 999));
56
+ }
57
+ function diffDaysInclusive(dateFrom, dateTo) {
58
+ return (Math.floor((toUtcDayStart(dateTo).getTime() - toUtcDayStart(dateFrom).getTime()) /
59
+ (24 * 60 * 60 * 1000)) + 1);
60
+ }
61
+ function shiftDays(value, days) {
62
+ const next = new Date(value);
63
+ next.setUTCDate(next.getUTCDate() + days);
64
+ return next;
65
+ }
66
+ function roundValue(value, precision) {
67
+ if (value === null || !Number.isFinite(value)) {
68
+ return null;
69
+ }
70
+ return Number(value.toFixed(precision));
71
+ }
72
+ function parseFrequencyToken(token) {
73
+ const [interval, rawValue] = token.split(":");
74
+ const parsedValue = Number.parseInt(rawValue ?? "", 10);
75
+ if (!interval ||
76
+ !["week", "month", "year"].includes(interval) ||
77
+ !Number.isFinite(parsedValue) ||
78
+ parsedValue <= 0) {
79
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Unsupported frequency token '${token}'`);
80
+ }
81
+ return {
82
+ interval: interval,
83
+ value: parsedValue,
84
+ };
85
+ }
86
+ function normalizeFrequencyFilters(filters) {
87
+ if (!filters?.length) {
88
+ return [];
89
+ }
90
+ return filters.map((filter) => {
91
+ if (typeof filter === "string") {
92
+ return parseFrequencyToken(filter);
93
+ }
94
+ if (!["week", "month", "year"].includes(filter.interval) ||
95
+ !Number.isFinite(filter.value) ||
96
+ filter.value <= 0) {
97
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Unsupported frequency filter '${filter.interval}:${filter.value}'`);
98
+ }
99
+ return {
100
+ interval: filter.interval,
101
+ value: filter.value,
102
+ };
103
+ });
104
+ }
105
+ function normalizeAnalyticsQueryInput(input) {
106
+ const now = new Date();
107
+ const resolvedTo = input.date_to ? toUtcDayEnd(input.date_to) : toUtcDayEnd(now);
108
+ const resolvedFrom = input.date_from
109
+ ? toUtcDayStart(input.date_from)
110
+ : toUtcDayStart(shiftDays(resolvedTo, -(DEFAULT_LOOKBACK_DAYS - 1)));
111
+ if (resolvedFrom.getTime() > resolvedTo.getTime()) {
112
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Analytics 'date_from' must be less than or equal to 'date_to'");
113
+ }
114
+ const timezone = input.timezone ?? DEFAULT_ANALYTICS_TIMEZONE;
115
+ if (timezone !== DEFAULT_ANALYTICS_TIMEZONE) {
116
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Unsupported analytics timezone '${timezone}'. Only 'UTC' is supported in MVP`);
117
+ }
118
+ const requestedWindowDays = diffDaysInclusive(resolvedFrom, resolvedTo);
119
+ if (requestedWindowDays > MAX_ANALYTICS_WINDOW_DAYS) {
120
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Analytics query window can't exceed ${MAX_ANALYTICS_WINDOW_DAYS} days`);
121
+ }
122
+ const groupBy = input.group_by ?? analytics_1.AnalyticsGroupBy.DAY;
123
+ return {
124
+ filters: {
125
+ date_from: resolvedFrom.toISOString(),
126
+ date_to: resolvedTo.toISOString(),
127
+ status: input.status ?? [],
128
+ product_id: input.product_id ?? [],
129
+ frequency: normalizeFrequencyFilters(input.frequency),
130
+ group_by: groupBy,
131
+ },
132
+ format: input.format ?? "json",
133
+ };
134
+ }
135
+ async function listMetricsDailyRows(container, filters) {
136
+ const query = getQuery(container);
137
+ const rows = [];
138
+ const take = 500;
139
+ let skip = 0;
140
+ while (true) {
141
+ const result = await query.graph({
142
+ entity: "subscription_metrics_daily",
143
+ fields: [
144
+ "id",
145
+ "metric_date",
146
+ "subscription_id",
147
+ "customer_id",
148
+ "product_id",
149
+ "variant_id",
150
+ "status",
151
+ "frequency_interval",
152
+ "frequency_value",
153
+ "currency_code",
154
+ "is_active",
155
+ "active_subscriptions_count",
156
+ "mrr_amount",
157
+ "churned_subscriptions_count",
158
+ "churn_reason_category",
159
+ ],
160
+ filters: {
161
+ metric_date: {
162
+ $gte: filters.date_from,
163
+ $lte: filters.date_to,
164
+ },
165
+ ...(filters.status.length ? { status: filters.status } : {}),
166
+ ...(filters.product_id.length ? { product_id: filters.product_id } : {}),
167
+ },
168
+ pagination: {
169
+ take,
170
+ skip,
171
+ order: {
172
+ metric_date: "ASC",
173
+ id: "ASC",
174
+ },
175
+ },
176
+ });
177
+ const batch = (result.data ?? []);
178
+ rows.push(...batch);
179
+ if (!batch.length || rows.length >= (result.metadata?.count ?? 0)) {
180
+ break;
181
+ }
182
+ skip += result.metadata?.take ?? take;
183
+ }
184
+ if (!filters.frequency.length) {
185
+ return rows;
186
+ }
187
+ const allowedTokens = new Set(filters.frequency.map((frequency) => `${frequency.interval}:${frequency.value}`));
188
+ return rows.filter((row) => allowedTokens.has(`${row.frequency_interval}:${row.frequency_value}`));
189
+ }
190
+ function buildDaySummaries(rows) {
191
+ const summaryByDay = new Map();
192
+ for (const row of rows) {
193
+ const metricDate = toUtcDayStart(row.metric_date).toISOString();
194
+ const current = summaryByDay.get(metricDate) ?? {
195
+ metric_date: metricDate,
196
+ active_subscriptions_count: 0,
197
+ churned_subscriptions_count: 0,
198
+ mrr_amount: 0,
199
+ currency_code: null,
200
+ has_mixed_currency: false,
201
+ };
202
+ current.active_subscriptions_count += Number(row.active_subscriptions_count ?? 0);
203
+ current.churned_subscriptions_count += Number(row.churned_subscriptions_count ?? 0);
204
+ const mrrAmount = row.mrr_amount === null || row.mrr_amount === undefined
205
+ ? null
206
+ : Number(row.mrr_amount);
207
+ if (current.has_mixed_currency) {
208
+ summaryByDay.set(metricDate, current);
209
+ continue;
210
+ }
211
+ if (mrrAmount !== null && Number.isFinite(mrrAmount)) {
212
+ current.mrr_amount = (current.mrr_amount ?? 0) + mrrAmount;
213
+ if (!current.currency_code) {
214
+ current.currency_code = row.currency_code ?? null;
215
+ }
216
+ else if (row.currency_code &&
217
+ current.currency_code &&
218
+ row.currency_code !== current.currency_code) {
219
+ current.has_mixed_currency = true;
220
+ current.mrr_amount = null;
221
+ current.currency_code = null;
222
+ }
223
+ }
224
+ summaryByDay.set(metricDate, current);
225
+ }
226
+ return [...summaryByDay.values()].sort((a, b) => a.metric_date.localeCompare(b.metric_date));
227
+ }
228
+ function getBucketBounds(metricDate, groupBy) {
229
+ if (groupBy === analytics_1.AnalyticsGroupBy.WEEK) {
230
+ return {
231
+ bucket_start: toUtcWeekStart(metricDate).toISOString(),
232
+ bucket_end: toUtcWeekEnd(metricDate).toISOString(),
233
+ };
234
+ }
235
+ if (groupBy === analytics_1.AnalyticsGroupBy.MONTH) {
236
+ return {
237
+ bucket_start: toUtcMonthStart(metricDate).toISOString(),
238
+ bucket_end: toUtcMonthEnd(metricDate).toISOString(),
239
+ };
240
+ }
241
+ return {
242
+ bucket_start: toUtcDayStart(metricDate).toISOString(),
243
+ bucket_end: toUtcDayEnd(metricDate).toISOString(),
244
+ };
245
+ }
246
+ function buildBucketSummaries(daySummaries, groupBy) {
247
+ const bucketMap = new Map();
248
+ for (const day of daySummaries) {
249
+ const bounds = getBucketBounds(day.metric_date, groupBy);
250
+ const current = bucketMap.get(bounds.bucket_start) ?? {
251
+ bucket_start: bounds.bucket_start,
252
+ bucket_end: bounds.bucket_end,
253
+ active_subscriptions_count: 0,
254
+ churned_subscriptions_count: 0,
255
+ avg_daily_active_subscriptions_count: 0,
256
+ mrr_amount: 0,
257
+ currency_code: null,
258
+ has_mixed_currency: false,
259
+ day_count: 0,
260
+ };
261
+ current.day_count += 1;
262
+ current.active_subscriptions_count = day.active_subscriptions_count;
263
+ current.avg_daily_active_subscriptions_count += day.active_subscriptions_count;
264
+ current.churned_subscriptions_count += day.churned_subscriptions_count;
265
+ if (day.has_mixed_currency) {
266
+ current.has_mixed_currency = true;
267
+ current.mrr_amount = null;
268
+ current.currency_code = null;
269
+ }
270
+ else if (!current.has_mixed_currency && day.mrr_amount !== null) {
271
+ current.mrr_amount = day.mrr_amount;
272
+ if (!current.currency_code) {
273
+ current.currency_code = day.currency_code;
274
+ }
275
+ else if (day.currency_code &&
276
+ current.currency_code &&
277
+ day.currency_code !== current.currency_code) {
278
+ current.has_mixed_currency = true;
279
+ current.mrr_amount = null;
280
+ current.currency_code = null;
281
+ }
282
+ }
283
+ bucketMap.set(bounds.bucket_start, current);
284
+ }
285
+ return [...bucketMap.values()]
286
+ .sort((a, b) => a.bucket_start.localeCompare(b.bucket_start))
287
+ .map((bucket) => ({
288
+ bucket_start: bucket.bucket_start,
289
+ bucket_end: bucket.bucket_end,
290
+ active_subscriptions_count: bucket.active_subscriptions_count,
291
+ churned_subscriptions_count: bucket.churned_subscriptions_count,
292
+ avg_daily_active_subscriptions_count: bucket.day_count
293
+ ? bucket.avg_daily_active_subscriptions_count / bucket.day_count
294
+ : 0,
295
+ mrr_amount: bucket.has_mixed_currency ? null : bucket.mrr_amount,
296
+ currency_code: bucket.has_mixed_currency ? null : bucket.currency_code,
297
+ has_mixed_currency: bucket.has_mixed_currency,
298
+ }));
299
+ }
300
+ function computeChurnRate(churnedCount, averageActiveBase) {
301
+ if (!averageActiveBase || averageActiveBase <= 0) {
302
+ return 0;
303
+ }
304
+ return (churnedCount / averageActiveBase) * 100;
305
+ }
306
+ function computeLtv(mrr, churnRate) {
307
+ if (mrr === null || churnRate <= 0) {
308
+ return null;
309
+ }
310
+ return mrr / (churnRate / 100);
311
+ }
312
+ function metricUnit(metric) {
313
+ if (metric === analytics_1.AnalyticsMetricKey.ACTIVE_SUBSCRIPTIONS_COUNT) {
314
+ return "count";
315
+ }
316
+ if (metric === analytics_1.AnalyticsMetricKey.CHURN_RATE) {
317
+ return "percentage";
318
+ }
319
+ return "currency";
320
+ }
321
+ function metricPrecision(metric) {
322
+ return metric === analytics_1.AnalyticsMetricKey.ACTIVE_SUBSCRIPTIONS_COUNT ? 0 : 2;
323
+ }
324
+ function buildKpiValue(metric, value, previousValue, currencyCode) {
325
+ const deltaValue = value === null || previousValue === null ? null : value - previousValue;
326
+ const deltaPercentage = deltaValue === null || previousValue === null || previousValue === 0
327
+ ? null
328
+ : (deltaValue / Math.abs(previousValue)) * 100;
329
+ return {
330
+ key: metric,
331
+ label: METRIC_LABELS[metric],
332
+ value: roundValue(value, metricPrecision(metric)),
333
+ unit: metricUnit(metric),
334
+ currency_code: metricUnit(metric) === "currency" ? currencyCode : null,
335
+ precision: metricPrecision(metric),
336
+ previous_value: roundValue(previousValue, metricPrecision(metric)),
337
+ delta_value: roundValue(deltaValue, metricPrecision(metric)),
338
+ delta_percentage: roundValue(deltaPercentage, 2),
339
+ };
340
+ }
341
+ function getLatestBucketValue(buckets, selector) {
342
+ if (!buckets.length) {
343
+ return null;
344
+ }
345
+ return selector(buckets[buckets.length - 1]);
346
+ }
347
+ function deriveKpiSet(buckets) {
348
+ const latestMrr = getLatestBucketValue(buckets, (bucket) => bucket.has_mixed_currency ? null : bucket.mrr_amount);
349
+ const latestCurrencyCode = buckets.length
350
+ ? buckets[buckets.length - 1].currency_code
351
+ : null;
352
+ const latestActiveCount = getLatestBucketValue(buckets, (bucket) => bucket.active_subscriptions_count);
353
+ const totalChurned = buckets.reduce((sum, bucket) => sum + bucket.churned_subscriptions_count, 0);
354
+ const averageActiveBase = buckets.length
355
+ ? buckets.reduce((sum, bucket) => sum + bucket.avg_daily_active_subscriptions_count, 0) / buckets.length
356
+ : 0;
357
+ const churnRate = computeChurnRate(totalChurned, averageActiveBase);
358
+ const ltv = computeLtv(latestMrr, churnRate);
359
+ return {
360
+ mrr: latestMrr,
361
+ mrr_currency_code: latestCurrencyCode,
362
+ active_subscriptions_count: latestActiveCount ?? 0,
363
+ churn_rate: churnRate,
364
+ ltv,
365
+ };
366
+ }
367
+ function buildTrendPoints(buckets, metric) {
368
+ return buckets.map((bucket) => {
369
+ let value;
370
+ if (metric === analytics_1.AnalyticsMetricKey.ACTIVE_SUBSCRIPTIONS_COUNT) {
371
+ value = bucket.active_subscriptions_count;
372
+ }
373
+ else if (metric === analytics_1.AnalyticsMetricKey.MRR) {
374
+ value = bucket.has_mixed_currency ? null : bucket.mrr_amount;
375
+ }
376
+ else if (metric === analytics_1.AnalyticsMetricKey.CHURN_RATE) {
377
+ value = computeChurnRate(bucket.churned_subscriptions_count, bucket.avg_daily_active_subscriptions_count);
378
+ }
379
+ else {
380
+ value = computeLtv(bucket.has_mixed_currency ? null : bucket.mrr_amount, computeChurnRate(bucket.churned_subscriptions_count, bucket.avg_daily_active_subscriptions_count));
381
+ }
382
+ return {
383
+ bucket_start: bucket.bucket_start,
384
+ bucket_end: bucket.bucket_end,
385
+ value: roundValue(value, metricPrecision(metric)),
386
+ };
387
+ });
388
+ }
389
+ function buildTrendSeries(buckets, metric) {
390
+ const currencyCode = metricUnit(metric) === "currency"
391
+ ? buckets.find((bucket) => bucket.currency_code)?.currency_code ?? null
392
+ : null;
393
+ return {
394
+ metric,
395
+ label: METRIC_LABELS[metric],
396
+ unit: metricUnit(metric),
397
+ currency_code: currencyCode,
398
+ precision: metricPrecision(metric),
399
+ points: buildTrendPoints(buckets, metric),
400
+ };
401
+ }
402
+ async function buildAnalyticsSnapshot(container, input) {
403
+ const normalized = normalizeAnalyticsQueryInput(input);
404
+ const currentRows = await listMetricsDailyRows(container, normalized.filters);
405
+ const currentDaySummaries = buildDaySummaries(currentRows);
406
+ const currentBuckets = buildBucketSummaries(currentDaySummaries, normalized.filters.group_by);
407
+ const resolvedFrom = new Date(normalized.filters.date_from ?? new Date());
408
+ const resolvedTo = new Date(normalized.filters.date_to ?? new Date());
409
+ const currentWindowDays = diffDaysInclusive(resolvedFrom, resolvedTo);
410
+ const previousTo = toUtcDayEnd(shiftDays(resolvedFrom, -1));
411
+ const previousFrom = toUtcDayStart(shiftDays(previousTo, -(currentWindowDays - 1)));
412
+ const previousFilters = {
413
+ ...normalized.filters,
414
+ date_from: previousFrom.toISOString(),
415
+ date_to: previousTo.toISOString(),
416
+ };
417
+ const previousRows = await listMetricsDailyRows(container, previousFilters);
418
+ const previousBuckets = buildBucketSummaries(buildDaySummaries(previousRows), normalized.filters.group_by);
419
+ return {
420
+ normalized,
421
+ currentBuckets,
422
+ previousBuckets,
423
+ };
424
+ }
425
+ async function getAdminAnalyticsKpis(container, input) {
426
+ const logger = getLogger(container);
427
+ const correlationId = (0, observability_1.createAnalyticsCorrelationId)("analytics-read-kpis");
428
+ const startedAt = Date.now();
429
+ try {
430
+ const snapshot = await buildAnalyticsSnapshot(container, input);
431
+ const currentSet = deriveKpiSet(snapshot.currentBuckets);
432
+ const previousSet = deriveKpiSet(snapshot.previousBuckets);
433
+ const response = {
434
+ filters: snapshot.normalized.filters,
435
+ metrics_version: constants_1.ANALYTICS_METRICS_VERSION,
436
+ generated_at: new Date().toISOString(),
437
+ kpis: [
438
+ buildKpiValue(analytics_1.AnalyticsMetricKey.MRR, currentSet.mrr, previousSet.mrr, currentSet.mrr_currency_code),
439
+ buildKpiValue(analytics_1.AnalyticsMetricKey.CHURN_RATE, currentSet.churn_rate, previousSet.churn_rate, null),
440
+ buildKpiValue(analytics_1.AnalyticsMetricKey.LTV, currentSet.ltv, previousSet.ltv, currentSet.mrr_currency_code),
441
+ buildKpiValue(analytics_1.AnalyticsMetricKey.ACTIVE_SUBSCRIPTIONS_COUNT, currentSet.active_subscriptions_count, previousSet.active_subscriptions_count, null),
442
+ ],
443
+ };
444
+ const durationMs = Date.now() - startedAt;
445
+ (0, observability_1.logAnalyticsEvent)(logger, (0, observability_1.getAnalyticsReadLogLevel)({
446
+ duration_ms: durationMs,
447
+ failed: false,
448
+ }), {
449
+ event: (0, observability_1.buildAnalyticsReadEventName)("kpis"),
450
+ outcome: "completed",
451
+ correlation_id: correlationId,
452
+ metrics_version: constants_1.ANALYTICS_METRICS_VERSION,
453
+ duration_ms: durationMs,
454
+ date_from: response.filters.date_from ?? undefined,
455
+ date_to: response.filters.date_to ?? undefined,
456
+ alertable: (0, observability_1.isSlowAnalyticsRead)(durationMs),
457
+ message: (0, observability_1.isSlowAnalyticsRead)(durationMs)
458
+ ? "Analytics KPI read completed slowly"
459
+ : "Analytics KPI read completed",
460
+ metadata: {
461
+ filters: response.filters,
462
+ bucket_count: snapshot.currentBuckets.length,
463
+ previous_bucket_count: snapshot.previousBuckets.length,
464
+ kpi_count: response.kpis.length,
465
+ },
466
+ });
467
+ return response;
468
+ }
469
+ catch (error) {
470
+ const durationMs = Date.now() - startedAt;
471
+ (0, observability_1.logAnalyticsEvent)(logger, "error", {
472
+ event: (0, observability_1.buildAnalyticsReadEventName)("kpis"),
473
+ outcome: "failed",
474
+ correlation_id: correlationId,
475
+ metrics_version: constants_1.ANALYTICS_METRICS_VERSION,
476
+ duration_ms: durationMs,
477
+ alertable: true,
478
+ message: (0, observability_1.getAnalyticsErrorMessage)(error),
479
+ });
480
+ throw error;
481
+ }
482
+ }
483
+ async function getAdminAnalyticsTrends(container, input) {
484
+ const logger = getLogger(container);
485
+ const correlationId = (0, observability_1.createAnalyticsCorrelationId)("analytics-read-trends");
486
+ const startedAt = Date.now();
487
+ try {
488
+ const normalized = normalizeAnalyticsQueryInput(input);
489
+ const rows = await listMetricsDailyRows(container, normalized.filters);
490
+ const buckets = buildBucketSummaries(buildDaySummaries(rows), normalized.filters.group_by);
491
+ const response = {
492
+ filters: normalized.filters,
493
+ metrics_version: constants_1.ANALYTICS_METRICS_VERSION,
494
+ generated_at: new Date().toISOString(),
495
+ series: [
496
+ buildTrendSeries(buckets, analytics_1.AnalyticsMetricKey.MRR),
497
+ buildTrendSeries(buckets, analytics_1.AnalyticsMetricKey.CHURN_RATE),
498
+ buildTrendSeries(buckets, analytics_1.AnalyticsMetricKey.LTV),
499
+ buildTrendSeries(buckets, analytics_1.AnalyticsMetricKey.ACTIVE_SUBSCRIPTIONS_COUNT),
500
+ ],
501
+ };
502
+ const durationMs = Date.now() - startedAt;
503
+ (0, observability_1.logAnalyticsEvent)(logger, (0, observability_1.getAnalyticsReadLogLevel)({
504
+ duration_ms: durationMs,
505
+ failed: false,
506
+ }), {
507
+ event: (0, observability_1.buildAnalyticsReadEventName)("trends"),
508
+ outcome: "completed",
509
+ correlation_id: correlationId,
510
+ metrics_version: constants_1.ANALYTICS_METRICS_VERSION,
511
+ duration_ms: durationMs,
512
+ date_from: response.filters.date_from ?? undefined,
513
+ date_to: response.filters.date_to ?? undefined,
514
+ alertable: (0, observability_1.isSlowAnalyticsRead)(durationMs),
515
+ message: (0, observability_1.isSlowAnalyticsRead)(durationMs)
516
+ ? "Analytics trends read completed slowly"
517
+ : "Analytics trends read completed",
518
+ metadata: {
519
+ filters: response.filters,
520
+ row_count: rows.length,
521
+ bucket_count: buckets.length,
522
+ series_count: response.series.length,
523
+ },
524
+ });
525
+ return response;
526
+ }
527
+ catch (error) {
528
+ const durationMs = Date.now() - startedAt;
529
+ (0, observability_1.logAnalyticsEvent)(logger, "error", {
530
+ event: (0, observability_1.buildAnalyticsReadEventName)("trends"),
531
+ outcome: "failed",
532
+ correlation_id: correlationId,
533
+ metrics_version: constants_1.ANALYTICS_METRICS_VERSION,
534
+ duration_ms: durationMs,
535
+ alertable: true,
536
+ message: (0, observability_1.getAnalyticsErrorMessage)(error),
537
+ });
538
+ throw error;
539
+ }
540
+ }
541
+ async function getAdminAnalyticsExport(container, input) {
542
+ const logger = getLogger(container);
543
+ const correlationId = (0, observability_1.createAnalyticsCorrelationId)("analytics-read-export");
544
+ const startedAt = Date.now();
545
+ try {
546
+ const normalized = normalizeAnalyticsQueryInput(input);
547
+ const rows = await listMetricsDailyRows(container, normalized.filters);
548
+ const buckets = buildBucketSummaries(buildDaySummaries(rows), normalized.filters.group_by);
549
+ const series = [
550
+ buildTrendSeries(buckets, analytics_1.AnalyticsMetricKey.MRR),
551
+ buildTrendSeries(buckets, analytics_1.AnalyticsMetricKey.CHURN_RATE),
552
+ buildTrendSeries(buckets, analytics_1.AnalyticsMetricKey.LTV),
553
+ buildTrendSeries(buckets, analytics_1.AnalyticsMetricKey.ACTIVE_SUBSCRIPTIONS_COUNT),
554
+ ];
555
+ const rowCount = series[0]?.points.length ?? 0;
556
+ const columns = [
557
+ "bucket_start",
558
+ "bucket_end",
559
+ "mrr",
560
+ "churn_rate",
561
+ "ltv",
562
+ "active_subscriptions_count",
563
+ ];
564
+ const exportRows = [];
565
+ for (let index = 0; index < rowCount; index += 1) {
566
+ const mrrPoint = series.find((seriesItem) => seriesItem.metric === analytics_1.AnalyticsMetricKey.MRR)
567
+ ?.points[index] ?? null;
568
+ const churnPoint = series.find((seriesItem) => seriesItem.metric === analytics_1.AnalyticsMetricKey.CHURN_RATE)
569
+ ?.points[index] ?? null;
570
+ const ltvPoint = series.find((seriesItem) => seriesItem.metric === analytics_1.AnalyticsMetricKey.LTV)
571
+ ?.points[index] ?? null;
572
+ const activePoint = series.find((seriesItem) => seriesItem.metric === analytics_1.AnalyticsMetricKey.ACTIVE_SUBSCRIPTIONS_COUNT)?.points[index] ?? null;
573
+ exportRows.push({
574
+ bucket_start: mrrPoint?.bucket_start ?? activePoint?.bucket_start ?? null,
575
+ bucket_end: mrrPoint?.bucket_end ?? activePoint?.bucket_end ?? null,
576
+ mrr: mrrPoint?.value ?? null,
577
+ churn_rate: churnPoint?.value ?? null,
578
+ ltv: ltvPoint?.value ?? null,
579
+ active_subscriptions_count: activePoint?.value ?? null,
580
+ });
581
+ }
582
+ const response = {
583
+ format: normalized.format,
584
+ filters: normalized.filters,
585
+ metrics_version: constants_1.ANALYTICS_METRICS_VERSION,
586
+ generated_at: new Date().toISOString(),
587
+ file_name: `subscription-analytics-${new Date().toISOString().slice(0, 10)}.${normalized.format}`,
588
+ content_type: normalized.format === "csv" ? "text/csv" : "application/json",
589
+ columns,
590
+ rows: exportRows,
591
+ };
592
+ const durationMs = Date.now() - startedAt;
593
+ (0, observability_1.logAnalyticsEvent)(logger, (0, observability_1.getAnalyticsReadLogLevel)({
594
+ duration_ms: durationMs,
595
+ failed: false,
596
+ }), {
597
+ event: (0, observability_1.buildAnalyticsReadEventName)("export"),
598
+ outcome: "completed",
599
+ correlation_id: correlationId,
600
+ metrics_version: constants_1.ANALYTICS_METRICS_VERSION,
601
+ duration_ms: durationMs,
602
+ date_from: response.filters.date_from ?? undefined,
603
+ date_to: response.filters.date_to ?? undefined,
604
+ alertable: (0, observability_1.isSlowAnalyticsRead)(durationMs),
605
+ message: (0, observability_1.isSlowAnalyticsRead)(durationMs)
606
+ ? "Analytics export read completed slowly"
607
+ : "Analytics export read completed",
608
+ metadata: {
609
+ filters: response.filters,
610
+ format: response.format,
611
+ row_count: response.rows.length,
612
+ bucket_count: buckets.length,
613
+ column_count: response.columns.length,
614
+ },
615
+ });
616
+ return response;
617
+ }
618
+ catch (error) {
619
+ const durationMs = Date.now() - startedAt;
620
+ (0, observability_1.logAnalyticsEvent)(logger, "error", {
621
+ event: (0, observability_1.buildAnalyticsReadEventName)("export"),
622
+ outcome: "failed",
623
+ correlation_id: correlationId,
624
+ metrics_version: constants_1.ANALYTICS_METRICS_VERSION,
625
+ duration_ms: durationMs,
626
+ alertable: true,
627
+ message: (0, observability_1.getAnalyticsErrorMessage)(error),
628
+ });
629
+ throw error;
630
+ }
631
+ }
632
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRtaW4tcXVlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9hbmFseXRpY3MvdXRpbHMvYWRtaW4tcXVlcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUF3c0JBLHNEQXdGQztBQUVELDBEQXVFQztBQUVELDBEQXFIQztBQS85QkQscURBQXVEO0FBQ3ZELHFEQUFxRTtBQUNyRSw4REFjdUM7QUFDdkMsNENBQXdEO0FBQ3hELG1EQU93QjtBQXFFeEIsTUFBTSxxQkFBcUIsR0FBRyxFQUFFLENBQUE7QUFDaEMsTUFBTSwwQkFBMEIsR0FBRyxLQUFLLENBQUE7QUFDeEMsTUFBTSx5QkFBeUIsR0FBRyxHQUFHLENBQUE7QUFDckMsTUFBTSxhQUFhLEdBQXVDO0lBQ3hELENBQUMsOEJBQWtCLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSztJQUMvQixDQUFDLDhCQUFrQixDQUFDLFVBQVUsQ0FBQyxFQUFFLFlBQVk7SUFDN0MsQ0FBQyw4QkFBa0IsQ0FBQyxHQUFHLENBQUMsRUFBRSxLQUFLO0lBQy9CLENBQUMsOEJBQWtCLENBQUMsMEJBQTBCLENBQUMsRUFBRSxzQkFBc0I7Q0FDeEUsQ0FBQTtBQUVELFNBQVMsUUFBUSxDQUFDLFNBQTBCO0lBQzFDLE9BQU8sU0FBUyxDQUFDLE9BQU8sQ0FBWSxpQ0FBeUIsQ0FBQyxLQUFLLENBQUMsQ0FBQTtBQUN0RSxDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsU0FBMEI7SUFDM0MsT0FBTyxTQUFTLENBQUMsT0FBTyxDQUlyQixRQUFRLENBQUMsQ0FBQTtBQUNkLENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxLQUFvQjtJQUN6QyxNQUFNLE1BQU0sR0FBRyxLQUFLLFlBQVksSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7SUFFeEUsT0FB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