medusa-stats 1.0.5

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 (180) hide show
  1. package/.medusa/server/src/admin/composite.png +0 -0
  2. package/.medusa/server/src/admin/index.js +10512 -0
  3. package/.medusa/server/src/admin/index.mjs +10510 -0
  4. package/.medusa/server/src/admin/params.png +0 -0
  5. package/.medusa/server/src/admin/view.png +0 -0
  6. package/.medusa/server/src/admin/visualizations.png +0 -0
  7. package/.medusa/server/src/api/admin/statistics/alert-logs/[id]/route.d.ts +6 -0
  8. package/.medusa/server/src/api/admin/statistics/alert-logs/[id]/route.js +18 -0
  9. package/.medusa/server/src/api/admin/statistics/alert-logs/route.d.ts +6 -0
  10. package/.medusa/server/src/api/admin/statistics/alert-logs/route.js +33 -0
  11. package/.medusa/server/src/api/admin/statistics/alerts/[id]/logs/route.d.ts +6 -0
  12. package/.medusa/server/src/api/admin/statistics/alerts/[id]/logs/route.js +23 -0
  13. package/.medusa/server/src/api/admin/statistics/alerts/[id]/route.d.ts +17 -0
  14. package/.medusa/server/src/api/admin/statistics/alerts/[id]/route.js +64 -0
  15. package/.medusa/server/src/api/admin/statistics/alerts/[id]/toggle/route.d.ts +6 -0
  16. package/.medusa/server/src/api/admin/statistics/alerts/[id]/toggle/route.js +18 -0
  17. package/.medusa/server/src/api/admin/statistics/alerts/route.d.ts +12 -0
  18. package/.medusa/server/src/api/admin/statistics/alerts/route.js +94 -0
  19. package/.medusa/server/src/api/admin/statistics/charts/[id]/route.d.ts +17 -0
  20. package/.medusa/server/src/api/admin/statistics/charts/[id]/route.js +50 -0
  21. package/.medusa/server/src/api/admin/statistics/charts/[id]/statistics/route.d.ts +15 -0
  22. package/.medusa/server/src/api/admin/statistics/charts/[id]/statistics/route.js +40 -0
  23. package/.medusa/server/src/api/admin/statistics/charts/route.d.ts +4 -0
  24. package/.medusa/server/src/api/admin/statistics/charts/route.js +55 -0
  25. package/.medusa/server/src/api/admin/statistics/options/[id]/calculate/route.d.ts +7 -0
  26. package/.medusa/server/src/api/admin/statistics/options/[id]/calculate/route.js +23 -0
  27. package/.medusa/server/src/api/admin/statistics/options/[id]/clone/route.d.ts +7 -0
  28. package/.medusa/server/src/api/admin/statistics/options/[id]/clone/route.js +15 -0
  29. package/.medusa/server/src/api/admin/statistics/options/[id]/route.d.ts +17 -0
  30. package/.medusa/server/src/api/admin/statistics/options/[id]/route.js +69 -0
  31. package/.medusa/server/src/api/admin/statistics/options/route.d.ts +12 -0
  32. package/.medusa/server/src/api/admin/statistics/options/route.js +87 -0
  33. package/.medusa/server/src/api/admin/statistics/providers/[id]/route.d.ts +6 -0
  34. package/.medusa/server/src/api/admin/statistics/providers/[id]/route.js +18 -0
  35. package/.medusa/server/src/api/admin/statistics/providers/[id]/statistics/route.d.ts +6 -0
  36. package/.medusa/server/src/api/admin/statistics/providers/[id]/statistics/route.js +18 -0
  37. package/.medusa/server/src/api/admin/statistics/providers/route.d.ts +7 -0
  38. package/.medusa/server/src/api/admin/statistics/providers/route.js +57 -0
  39. package/.medusa/server/src/api/admin/statistics/utils/option-graph.d.ts +3 -0
  40. package/.medusa/server/src/api/admin/statistics/utils/option-graph.js +34 -0
  41. package/.medusa/server/src/api/admin/statistics/views/[id]/calculate/route.d.ts +7 -0
  42. package/.medusa/server/src/api/admin/statistics/views/[id]/calculate/route.js +21 -0
  43. package/.medusa/server/src/api/admin/statistics/views/[id]/clone/route.d.ts +7 -0
  44. package/.medusa/server/src/api/admin/statistics/views/[id]/clone/route.js +21 -0
  45. package/.medusa/server/src/api/admin/statistics/views/[id]/route.d.ts +17 -0
  46. package/.medusa/server/src/api/admin/statistics/views/[id]/route.js +71 -0
  47. package/.medusa/server/src/api/admin/statistics/views/route.d.ts +12 -0
  48. package/.medusa/server/src/api/admin/statistics/views/route.js +74 -0
  49. package/.medusa/server/src/api/middlewares.d.ts +2 -0
  50. package/.medusa/server/src/api/middlewares.js +194 -0
  51. package/.medusa/server/src/api/validation/statistics/schemas.d.ts +1013 -0
  52. package/.medusa/server/src/api/validation/statistics/schemas.js +288 -0
  53. package/.medusa/server/src/index.d.ts +1 -0
  54. package/.medusa/server/src/index.js +18 -0
  55. package/.medusa/server/src/jobs/evaluate-statistics-alerts.d.ts +6 -0
  56. package/.medusa/server/src/jobs/evaluate-statistics-alerts.js +110 -0
  57. package/.medusa/server/src/links/statistics-alert-user.d.ts +2 -0
  58. package/.medusa/server/src/links/statistics-alert-user.js +16 -0
  59. package/.medusa/server/src/links/statistics-option-user.d.ts +2 -0
  60. package/.medusa/server/src/links/statistics-option-user.js +16 -0
  61. package/.medusa/server/src/loaders/statistics/index.d.ts +5 -0
  62. package/.medusa/server/src/loaders/statistics/index.js +47 -0
  63. package/.medusa/server/src/modules/statistics/index.d.ts +107 -0
  64. package/.medusa/server/src/modules/statistics/index.js +32 -0
  65. package/.medusa/server/src/modules/statistics/migrations/Migration20260223131741.d.ts +5 -0
  66. package/.medusa/server/src/modules/statistics/migrations/Migration20260223131741.js +57 -0
  67. package/.medusa/server/src/modules/statistics/models/alert-log.d.ts +74 -0
  68. package/.medusa/server/src/modules/statistics/models/alert-log.js +16 -0
  69. package/.medusa/server/src/modules/statistics/models/alert.d.ts +74 -0
  70. package/.medusa/server/src/modules/statistics/models/alert.js +24 -0
  71. package/.medusa/server/src/modules/statistics/models/chart.d.ts +81 -0
  72. package/.medusa/server/src/modules/statistics/models/chart.js +28 -0
  73. package/.medusa/server/src/modules/statistics/models/index.d.ts +7 -0
  74. package/.medusa/server/src/modules/statistics/models/index.js +24 -0
  75. package/.medusa/server/src/modules/statistics/models/option-input.d.ts +135 -0
  76. package/.medusa/server/src/modules/statistics/models/option-input.js +27 -0
  77. package/.medusa/server/src/modules/statistics/models/option.d.ts +78 -0
  78. package/.medusa/server/src/modules/statistics/models/option.js +41 -0
  79. package/.medusa/server/src/modules/statistics/models/provider.d.ts +75 -0
  80. package/.medusa/server/src/modules/statistics/models/provider.js +15 -0
  81. package/.medusa/server/src/modules/statistics/models/view.d.ts +79 -0
  82. package/.medusa/server/src/modules/statistics/models/view.js +30 -0
  83. package/.medusa/server/src/modules/statistics/providers/index.d.ts +1 -0
  84. package/.medusa/server/src/modules/statistics/providers/index.js +18 -0
  85. package/.medusa/server/src/modules/statistics/providers/provider.d.ts +254 -0
  86. package/.medusa/server/src/modules/statistics/providers/provider.js +307 -0
  87. package/.medusa/server/src/modules/statistics/service.d.ts +953 -0
  88. package/.medusa/server/src/modules/statistics/service.js +190 -0
  89. package/.medusa/server/src/modules/statistics/utils/dependency-option-map.d.ts +13 -0
  90. package/.medusa/server/src/modules/statistics/utils/dependency-option-map.js +67 -0
  91. package/.medusa/server/src/modules/statistics/utils/period-utils.d.ts +23 -0
  92. package/.medusa/server/src/modules/statistics/utils/period-utils.js +78 -0
  93. package/.medusa/server/src/modules/statistics/utils/time-series-utils.d.ts +6 -0
  94. package/.medusa/server/src/modules/statistics/utils/time-series-utils.js +8 -0
  95. package/.medusa/server/src/providers/common/index.d.ts +2 -0
  96. package/.medusa/server/src/providers/common/index.js +1232 -0
  97. package/.medusa/server/src/providers/composite/index.d.ts +2 -0
  98. package/.medusa/server/src/providers/composite/index.js +147 -0
  99. package/.medusa/server/src/workflows/statistics/calculate-single-statistic.d.ts +15 -0
  100. package/.medusa/server/src/workflows/statistics/calculate-single-statistic.js +28 -0
  101. package/.medusa/server/src/workflows/statistics/calculate-statistics.d.ts +20 -0
  102. package/.medusa/server/src/workflows/statistics/calculate-statistics.js +15 -0
  103. package/.medusa/server/src/workflows/statistics/calculate-view.d.ts +31 -0
  104. package/.medusa/server/src/workflows/statistics/calculate-view.js +30 -0
  105. package/.medusa/server/src/workflows/statistics/clone-view.d.ts +227 -0
  106. package/.medusa/server/src/workflows/statistics/clone-view.js +10 -0
  107. package/.medusa/server/src/workflows/statistics/create-alert.d.ts +139 -0
  108. package/.medusa/server/src/workflows/statistics/create-alert.js +12 -0
  109. package/.medusa/server/src/workflows/statistics/create-chart.d.ts +122 -0
  110. package/.medusa/server/src/workflows/statistics/create-chart.js +14 -0
  111. package/.medusa/server/src/workflows/statistics/create-view-with-options.d.ts +1342 -0
  112. package/.medusa/server/src/workflows/statistics/create-view-with-options.js +29 -0
  113. package/.medusa/server/src/workflows/statistics/delete-chart.d.ts +10 -0
  114. package/.medusa/server/src/workflows/statistics/delete-chart.js +14 -0
  115. package/.medusa/server/src/workflows/statistics/evaluate-alerts.d.ts +28 -0
  116. package/.medusa/server/src/workflows/statistics/evaluate-alerts.js +67 -0
  117. package/.medusa/server/src/workflows/statistics/get-available-statistics.d.ts +5 -0
  118. package/.medusa/server/src/workflows/statistics/get-available-statistics.js +10 -0
  119. package/.medusa/server/src/workflows/statistics/index.d.ts +14 -0
  120. package/.medusa/server/src/workflows/statistics/index.js +31 -0
  121. package/.medusa/server/src/workflows/statistics/manage-chart-statistics.d.ts +12 -0
  122. package/.medusa/server/src/workflows/statistics/manage-chart-statistics.js +14 -0
  123. package/.medusa/server/src/workflows/statistics/steps/calculate-statistics.d.ts +37 -0
  124. package/.medusa/server/src/workflows/statistics/steps/calculate-statistics.js +222 -0
  125. package/.medusa/server/src/workflows/statistics/steps/clone-view.d.ts +227 -0
  126. package/.medusa/server/src/workflows/statistics/steps/clone-view.js +39 -0
  127. package/.medusa/server/src/workflows/statistics/steps/create-alert-log-entries.d.ts +17 -0
  128. package/.medusa/server/src/workflows/statistics/steps/create-alert-log-entries.js +50 -0
  129. package/.medusa/server/src/workflows/statistics/steps/create-alert.d.ts +120 -0
  130. package/.medusa/server/src/workflows/statistics/steps/create-alert.js +21 -0
  131. package/.medusa/server/src/workflows/statistics/steps/create-chart.d.ts +118 -0
  132. package/.medusa/server/src/workflows/statistics/steps/create-chart.js +19 -0
  133. package/.medusa/server/src/workflows/statistics/steps/create-statistics-options.d.ts +117 -0
  134. package/.medusa/server/src/workflows/statistics/steps/create-statistics-options.js +16 -0
  135. package/.medusa/server/src/workflows/statistics/steps/create-statistics-view.d.ts +119 -0
  136. package/.medusa/server/src/workflows/statistics/steps/create-statistics-view.js +16 -0
  137. package/.medusa/server/src/workflows/statistics/steps/dedupe-alerts.d.ts +22 -0
  138. package/.medusa/server/src/workflows/statistics/steps/dedupe-alerts.js +64 -0
  139. package/.medusa/server/src/workflows/statistics/steps/delete-chart.d.ts +6 -0
  140. package/.medusa/server/src/workflows/statistics/steps/delete-chart.js +17 -0
  141. package/.medusa/server/src/workflows/statistics/steps/emit-alert-events.d.ts +17 -0
  142. package/.medusa/server/src/workflows/statistics/steps/emit-alert-events.js +41 -0
  143. package/.medusa/server/src/workflows/statistics/steps/evaluate-each-condition.d.ts +15 -0
  144. package/.medusa/server/src/workflows/statistics/steps/evaluate-each-condition.js +109 -0
  145. package/.medusa/server/src/workflows/statistics/steps/extract-alert-values.d.ts +12 -0
  146. package/.medusa/server/src/workflows/statistics/steps/extract-alert-values.js +86 -0
  147. package/.medusa/server/src/workflows/statistics/steps/fetch-active-alerts-for-option.d.ts +112 -0
  148. package/.medusa/server/src/workflows/statistics/steps/fetch-active-alerts-for-option.js +16 -0
  149. package/.medusa/server/src/workflows/statistics/steps/fetch-available-statistics.d.ts +4 -0
  150. package/.medusa/server/src/workflows/statistics/steps/fetch-available-statistics.js +39 -0
  151. package/.medusa/server/src/workflows/statistics/steps/fetch-option-with-relations.d.ts +112 -0
  152. package/.medusa/server/src/workflows/statistics/steps/fetch-option-with-relations.js +11 -0
  153. package/.medusa/server/src/workflows/statistics/steps/fetch-view-with-options.d.ts +112 -0
  154. package/.medusa/server/src/workflows/statistics/steps/fetch-view-with-options.js +20 -0
  155. package/.medusa/server/src/workflows/statistics/steps/manage-chart-statistics.d.ts +8 -0
  156. package/.medusa/server/src/workflows/statistics/steps/manage-chart-statistics.js +26 -0
  157. package/.medusa/server/src/workflows/statistics/steps/update-chart.d.ts +117 -0
  158. package/.medusa/server/src/workflows/statistics/steps/update-chart.js +32 -0
  159. package/.medusa/server/src/workflows/statistics/steps/update-view.d.ts +120 -0
  160. package/.medusa/server/src/workflows/statistics/steps/update-view.js +18 -0
  161. package/.medusa/server/src/workflows/statistics/steps/validate-alert-input.d.ts +1 -0
  162. package/.medusa/server/src/workflows/statistics/steps/validate-alert-input.js +34 -0
  163. package/.medusa/server/src/workflows/statistics/steps/validate-option-parameters.d.ts +21 -0
  164. package/.medusa/server/src/workflows/statistics/steps/validate-option-parameters.js +43 -0
  165. package/.medusa/server/src/workflows/statistics/steps/validate-view-input.d.ts +10 -0
  166. package/.medusa/server/src/workflows/statistics/steps/validate-view-input.js +15 -0
  167. package/.medusa/server/src/workflows/statistics/update-chart.d.ts +120 -0
  168. package/.medusa/server/src/workflows/statistics/update-chart.js +13 -0
  169. package/.medusa/server/src/workflows/statistics/update-view-configuration.d.ts +128 -0
  170. package/.medusa/server/src/workflows/statistics/update-view-configuration.js +18 -0
  171. package/.medusa/server/src/workflows/statistics/utils/cache-utils.d.ts +60 -0
  172. package/.medusa/server/src/workflows/statistics/utils/cache-utils.js +66 -0
  173. package/.medusa/server/src/workflows/statistics/utils/dependency-graph.d.ts +51 -0
  174. package/.medusa/server/src/workflows/statistics/utils/dependency-graph.js +131 -0
  175. package/.medusa/server/src/workflows/statistics/utils/parameter-utils.d.ts +54 -0
  176. package/.medusa/server/src/workflows/statistics/utils/parameter-utils.js +147 -0
  177. package/.medusa/server/src/workflows/statistics/validate-option-configuration.d.ts +9 -0
  178. package/.medusa/server/src/workflows/statistics/validate-option-configuration.js +35 -0
  179. package/README.md +310 -0
  180. package/package.json +87 -0
@@ -0,0 +1,254 @@
1
+ import { z } from "zod";
2
+ export type ParameterFieldType = "text" | "number" | "select" | "multiselect" | "boolean" | "date" | "daterange" | "currency" | "json" | "entity" | "entities" | "custom" | "stat";
3
+ export interface EntityReference {
4
+ entity: string;
5
+ }
6
+ export interface ParameterFieldDefinition {
7
+ name: string;
8
+ label: string;
9
+ description?: string;
10
+ placeholder?: string;
11
+ schema?: z.ZodType<any>;
12
+ fieldType: ParameterFieldType;
13
+ options?: Array<{
14
+ value: string | number | boolean;
15
+ label: string;
16
+ description?: string;
17
+ disabled?: boolean;
18
+ }> | ((context: Record<string, any>) => Promise<Array<any>> | Array<any>);
19
+ entityReference?: EntityReference;
20
+ dependsOn?: Array<{
21
+ field: string;
22
+ condition: (value: any, allValues: Record<string, any>) => boolean;
23
+ effect?: "show" | "hide" | "enable" | "disable" | "require";
24
+ }>;
25
+ }
26
+ export interface AvailableStatistic {
27
+ id: string;
28
+ name: string;
29
+ description?: string;
30
+ parameters: {
31
+ fields: ParameterFieldDefinition[];
32
+ defaults?: Record<string, any>;
33
+ };
34
+ display: {
35
+ visualization?: {
36
+ preferredChartType?: "line" | "bar" | "area" | "pie" | "gauge" | "number" | string;
37
+ xAxisType?: "time" | "category";
38
+ [key: string]: any;
39
+ };
40
+ };
41
+ metadata?: Record<string, any>;
42
+ }
43
+ export interface CalculateStatisticInput {
44
+ id: string;
45
+ parameters: Record<string, any>;
46
+ fields: ParameterFieldDefinition[];
47
+ periodStart: Date;
48
+ periodEnd: Date;
49
+ interval: number;
50
+ metadata?: Record<string, any>;
51
+ }
52
+ export type TimeSeries = Array<{
53
+ x: Date;
54
+ value: any;
55
+ }>;
56
+ export type CategoricalSeries = Array<{
57
+ x: string | number;
58
+ value: any;
59
+ }>;
60
+ export type GaugeValue = {
61
+ value: number;
62
+ };
63
+ export interface StatisticResult {
64
+ value: TimeSeries | CategoricalSeries | GaugeValue | any;
65
+ metadata?: Record<string, any>;
66
+ }
67
+ /**
68
+ * Builder class for constructing AvailableStatistic objects with a fluent API.
69
+ *
70
+ * @example
71
+ * const statistic = new StatBuilder("total_revenue", "Total Revenue")
72
+ * .description("Calculate total revenue for the period")
73
+ * .field({
74
+ * name: "currency_code",
75
+ * label: "Currency",
76
+ * fieldType: "select",
77
+ * options: [{ value: "usd", label: "USD" }]
78
+ * })
79
+ * .chart("line")
80
+ * .dimension("time")
81
+ * .build();
82
+ */
83
+ export declare class StatBuilder {
84
+ private statistic;
85
+ constructor(id: string, name: string);
86
+ /**
87
+ * Set the description for this statistic
88
+ */
89
+ description(description: string): this;
90
+ /**
91
+ * Add a single parameter field to this statistic
92
+ */
93
+ field(field: ParameterFieldDefinition, defaultValue?: any): this;
94
+ /**
95
+ * Set the preferred chart type for visualization
96
+ */
97
+ chart(chartType: "line" | "bar" | "area" | "pie" | "gauge" | "number" | string): this;
98
+ /**
99
+ * Set the X-axis type for time series or categorical data
100
+ */
101
+ dimension(type: "time" | "category"): this;
102
+ /**
103
+ * Set visualization configuration (merges with existing config)
104
+ */
105
+ visualization(config: Partial<AvailableStatistic['display']['visualization']>): this;
106
+ /**
107
+ * Set metadata for this statistic
108
+ */
109
+ metadata(metadata: Record<string, any>): this;
110
+ /**
111
+ * Build and return the final AvailableStatistic object
112
+ */
113
+ build(): AvailableStatistic;
114
+ }
115
+ /**
116
+ * Helper: Group an array of data by a property or function result
117
+ *
118
+ * @param data - Array of data items to group
119
+ * @param keySelector - Property name or function to extract grouping key
120
+ * @param aggregator - Optional function to aggregate grouped values
121
+ * @returns Map of grouped data
122
+ *
123
+ * @example
124
+ *
125
+ * const byDate = groupBy(orders, 'created_at')
126
+ *
127
+ * @example
128
+ *
129
+ * const revenueByDay = groupBy(
130
+ * orders,
131
+ * (order) => order.created_at.toISOString().split('T')[0],
132
+ * (items) => items.reduce((sum, item) => sum + item.total, 0)
133
+ * )
134
+ */
135
+ export declare function groupBy<T, K extends string | number = string>(data: T[], keySelector: keyof T | ((item: T) => K), aggregator?: (items: T[], key: K) => any): Map<K, any>;
136
+ /**
137
+ * Helper: Generate interval timestamps for a period
138
+ *
139
+ * @param periodStart - Start date of the period
140
+ * @param periodEnd - End date of the period
141
+ * @param interval - Interval in seconds (3600 = hourly, 86400 = daily, 604800 = weekly)
142
+ * @returns Array of timestamps at each interval
143
+ *
144
+ * @example
145
+ * const intervals = generateIntervals(
146
+ * new Date('2024-01-01'),
147
+ * new Date('2024-01-31'),
148
+ * 604800
149
+ * )
150
+ */
151
+ export declare function generateIntervals(periodStart: Date, periodEnd: Date, interval: number): Date[];
152
+ /**
153
+ * Helper: Get the interval bucket for a given date
154
+ *
155
+ * @param date - Date to bucket
156
+ * @param periodStart - Start of the period
157
+ * @param interval - Interval in seconds
158
+ * @returns The bucket date (start of interval)
159
+ *
160
+ * @example
161
+ * const bucketDate = getIntervalBucket(
162
+ * new Date('2024-01-05'),
163
+ * new Date('2024-01-01'),
164
+ * 604800
165
+ * )
166
+ */
167
+ export declare function getIntervalBucket(date: Date, periodStart: Date, interval: number): Date;
168
+ /**
169
+ * Creates a time series by efficiently mapping data to time intervals.
170
+ * Generates intervals internally and processes data in a single pass.
171
+ *
172
+ * @param data - Array of data items to aggregate
173
+ * @param periodStart - Start of the time period
174
+ * @param periodEnd - End of the time period
175
+ * @param intervalSeconds - Duration of each interval in seconds
176
+ * @param accumulator - Function to aggregate items within each interval
177
+ * @param options - Optional configuration
178
+ * @param options.timestampField - Field name or function to extract timestamp (defaults to 'created_at')
179
+ * @returns Array of time series points with x (Date) and value (number)
180
+ */
181
+ export declare function createTimeSeries<T extends Record<string, any>>(data: T[], periodStart: Date, periodEnd: Date, intervalSeconds: number, accumulator: (items: T[]) => number, options?: {
182
+ timestampField?: string | ((item: T) => number);
183
+ }): Array<{
184
+ x: Date;
185
+ value: number;
186
+ }>;
187
+ /**
188
+ * Creates a count accumulator that returns the number of items.
189
+ *
190
+ * @returns Accumulator function that counts items
191
+ *
192
+ * @example
193
+ * createTimeSeries(orders, start, end, interval, count())
194
+ */
195
+ export declare function count<T>(): (items: T[]) => number;
196
+ /**
197
+ * Creates a sum accumulator that sums values of a specific field.
198
+ *
199
+ * @param field - Name of the field to sum
200
+ * @returns Accumulator function that sums field values
201
+ *
202
+ * @example
203
+ * createTimeSeries(orders, start, end, interval, sum('total'))
204
+ */
205
+ export declare function sum<T extends Record<string, any>>(field: string): (items: T[]) => number;
206
+ /**
207
+ * Creates an average accumulator that calculates mean of a specific field.
208
+ * Optionally excludes outliers using IQR method (requires at least 3 data points).
209
+ *
210
+ * @param field - Name of the field to average
211
+ * @param options - Optional configuration
212
+ * @param options.excludeOutliers - If true, excludes outliers using IQR method
213
+ * @returns Accumulator function that calculates average
214
+ *
215
+ * @example
216
+ * createTimeSeries(orders, start, end, interval, average('total'))
217
+ * createTimeSeries(orders, start, end, interval, average('total', { excludeOutliers: true }))
218
+ */
219
+ export declare function average<T extends Record<string, any>>(field: string, options?: {
220
+ excludeOutliers?: boolean;
221
+ }): (items: T[]) => number;
222
+ /**
223
+ * Abstract provider for calculating statistics.
224
+ * Extend this class to implement custom statistics providers.
225
+ */
226
+ export declare abstract class AbstractStatisticsProvider {
227
+ protected readonly container: any;
228
+ static identifier: string;
229
+ static displayName: string;
230
+ protected query: any;
231
+ constructor(container: any);
232
+ /**
233
+ * Get available statistics for a given sales channel.
234
+ *
235
+ * @param input - Input parameters
236
+ * @param input.sales_channel_id - Optional sales channel ID to filter statistics
237
+ * @returns Array of available statistics with their configuration
238
+ */
239
+ abstract getAvailableStatistics(): Promise<AvailableStatistic[]> | AvailableStatistic[];
240
+ /**
241
+ * Calculate a specific statistic for a given period.
242
+ *
243
+ * @param input - Input parameters
244
+ * @param input.id - The statistic ID to calculate
245
+ * @param input.parameters - Validated and merged parameter values
246
+ * @param input.fields - Field definitions for reference
247
+ * @param input.periodStart - Start date of the period
248
+ * @param input.periodEnd - End date of the period
249
+ * @param input.interval - Interval in seconds (3600 = hourly, 86400 = daily, 604800 = weekly)
250
+ * @param input.metadata - Additional calculation metadata
251
+ * @returns The calculated statistic with rendering configuration
252
+ */
253
+ abstract calculateStatistic(input: CalculateStatisticInput): Promise<StatisticResult> | StatisticResult;
254
+ }
@@ -0,0 +1,307 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AbstractStatisticsProvider = exports.StatBuilder = void 0;
4
+ exports.groupBy = groupBy;
5
+ exports.generateIntervals = generateIntervals;
6
+ exports.getIntervalBucket = getIntervalBucket;
7
+ exports.createTimeSeries = createTimeSeries;
8
+ exports.count = count;
9
+ exports.sum = sum;
10
+ exports.average = average;
11
+ const utils_1 = require("@medusajs/framework/utils");
12
+ /**
13
+ * Builder class for constructing AvailableStatistic objects with a fluent API.
14
+ *
15
+ * @example
16
+ * const statistic = new StatBuilder("total_revenue", "Total Revenue")
17
+ * .description("Calculate total revenue for the period")
18
+ * .field({
19
+ * name: "currency_code",
20
+ * label: "Currency",
21
+ * fieldType: "select",
22
+ * options: [{ value: "usd", label: "USD" }]
23
+ * })
24
+ * .chart("line")
25
+ * .dimension("time")
26
+ * .build();
27
+ */
28
+ class StatBuilder {
29
+ constructor(id, name) {
30
+ this.statistic = {
31
+ id,
32
+ name,
33
+ parameters: {
34
+ fields: []
35
+ },
36
+ display: {}
37
+ };
38
+ }
39
+ /**
40
+ * Set the description for this statistic
41
+ */
42
+ description(description) {
43
+ this.statistic.description = description;
44
+ return this;
45
+ }
46
+ /**
47
+ * Add a single parameter field to this statistic
48
+ */
49
+ field(field, defaultValue) {
50
+ this.statistic.parameters.fields.push(field);
51
+ if (defaultValue !== undefined) {
52
+ if (!this.statistic.parameters.defaults) {
53
+ this.statistic.parameters.defaults = {};
54
+ }
55
+ this.statistic.parameters.defaults[field.name] = defaultValue;
56
+ }
57
+ return this;
58
+ }
59
+ /**
60
+ * Set the preferred chart type for visualization
61
+ */
62
+ chart(chartType) {
63
+ if (!this.statistic.display.visualization) {
64
+ this.statistic.display.visualization = {};
65
+ }
66
+ this.statistic.display.visualization.preferredChartType = chartType;
67
+ return this;
68
+ }
69
+ /**
70
+ * Set the X-axis type for time series or categorical data
71
+ */
72
+ dimension(type) {
73
+ if (!this.statistic.display.visualization) {
74
+ this.statistic.display.visualization = {};
75
+ }
76
+ this.statistic.display.visualization.xAxisType = type;
77
+ return this;
78
+ }
79
+ /**
80
+ * Set visualization configuration (merges with existing config)
81
+ */
82
+ visualization(config) {
83
+ this.statistic.display.visualization = {
84
+ ...this.statistic.display.visualization,
85
+ ...config
86
+ };
87
+ return this;
88
+ }
89
+ /**
90
+ * Set metadata for this statistic
91
+ */
92
+ metadata(metadata) {
93
+ this.statistic.metadata = metadata;
94
+ return this;
95
+ }
96
+ /**
97
+ * Build and return the final AvailableStatistic object
98
+ */
99
+ build() {
100
+ if (!this.statistic.id || !this.statistic.name) {
101
+ throw new Error("AvailableStatistic requires 'id' and 'name'");
102
+ }
103
+ return { ...this.statistic };
104
+ }
105
+ }
106
+ exports.StatBuilder = StatBuilder;
107
+ /**
108
+ * Helper: Group an array of data by a property or function result
109
+ *
110
+ * @param data - Array of data items to group
111
+ * @param keySelector - Property name or function to extract grouping key
112
+ * @param aggregator - Optional function to aggregate grouped values
113
+ * @returns Map of grouped data
114
+ *
115
+ * @example
116
+ *
117
+ * const byDate = groupBy(orders, 'created_at')
118
+ *
119
+ * @example
120
+ *
121
+ * const revenueByDay = groupBy(
122
+ * orders,
123
+ * (order) => order.created_at.toISOString().split('T')[0],
124
+ * (items) => items.reduce((sum, item) => sum + item.total, 0)
125
+ * )
126
+ */
127
+ function groupBy(data, keySelector, aggregator) {
128
+ const groups = new Map();
129
+ for (const item of data) {
130
+ const key = typeof keySelector === 'function'
131
+ ? keySelector(item)
132
+ : item[keySelector];
133
+ if (!groups.has(key)) {
134
+ groups.set(key, []);
135
+ }
136
+ groups.get(key).push(item);
137
+ }
138
+ if (aggregator) {
139
+ const result = new Map();
140
+ for (const [key, items] of groups.entries()) {
141
+ result.set(key, aggregator(items, key));
142
+ }
143
+ return result;
144
+ }
145
+ return groups;
146
+ }
147
+ /**
148
+ * Helper: Generate interval timestamps for a period
149
+ *
150
+ * @param periodStart - Start date of the period
151
+ * @param periodEnd - End date of the period
152
+ * @param interval - Interval in seconds (3600 = hourly, 86400 = daily, 604800 = weekly)
153
+ * @returns Array of timestamps at each interval
154
+ *
155
+ * @example
156
+ * const intervals = generateIntervals(
157
+ * new Date('2024-01-01'),
158
+ * new Date('2024-01-31'),
159
+ * 604800
160
+ * )
161
+ */
162
+ function generateIntervals(periodStart, periodEnd, interval) {
163
+ const intervals = [];
164
+ const current = new Date(periodStart);
165
+ const end = new Date(periodEnd);
166
+ const intervalMs = interval * 1000;
167
+ while (current <= end) {
168
+ intervals.push(new Date(current));
169
+ current.setTime(current.getTime() + intervalMs);
170
+ }
171
+ return intervals;
172
+ }
173
+ /**
174
+ * Helper: Get the interval bucket for a given date
175
+ *
176
+ * @param date - Date to bucket
177
+ * @param periodStart - Start of the period
178
+ * @param interval - Interval in seconds
179
+ * @returns The bucket date (start of interval)
180
+ *
181
+ * @example
182
+ * const bucketDate = getIntervalBucket(
183
+ * new Date('2024-01-05'),
184
+ * new Date('2024-01-01'),
185
+ * 604800
186
+ * )
187
+ */
188
+ function getIntervalBucket(date, periodStart, interval) {
189
+ const msSinceStart = date.getTime() - periodStart.getTime();
190
+ const secondsSinceStart = Math.floor(msSinceStart / 1000);
191
+ const bucketIndex = Math.floor(secondsSinceStart / interval);
192
+ const bucketDate = new Date(periodStart);
193
+ bucketDate.setTime(bucketDate.getTime() + bucketIndex * interval * 1000);
194
+ return bucketDate;
195
+ }
196
+ /**
197
+ * Creates a time series by efficiently mapping data to time intervals.
198
+ * Generates intervals internally and processes data in a single pass.
199
+ *
200
+ * @param data - Array of data items to aggregate
201
+ * @param periodStart - Start of the time period
202
+ * @param periodEnd - End of the time period
203
+ * @param intervalSeconds - Duration of each interval in seconds
204
+ * @param accumulator - Function to aggregate items within each interval
205
+ * @param options - Optional configuration
206
+ * @param options.timestampField - Field name or function to extract timestamp (defaults to 'created_at')
207
+ * @returns Array of time series points with x (Date) and value (number)
208
+ */
209
+ function createTimeSeries(data, periodStart, periodEnd, intervalSeconds, accumulator, options = {}) {
210
+ let getTimestamp;
211
+ if (typeof options.timestampField === 'function') {
212
+ getTimestamp = options.timestampField;
213
+ }
214
+ else {
215
+ const field = options.timestampField || 'created_at';
216
+ getTimestamp = (item) => new Date(item[field]).getTime();
217
+ }
218
+ const sorted = [...data]
219
+ .map(item => ({ item, timestamp: getTimestamp(item) }))
220
+ .sort((a, b) => a.timestamp - b.timestamp);
221
+ const result = [];
222
+ const startMs = periodStart.getTime();
223
+ const endMs = periodEnd.getTime();
224
+ const intervalMs = intervalSeconds * 1000;
225
+ let dataIdx = 0;
226
+ for (let currentMs = startMs; currentMs < endMs; currentMs += intervalMs) {
227
+ const nextMs = Math.min(currentMs + intervalMs, endMs);
228
+ const itemsInInterval = [];
229
+ const startIdx = dataIdx;
230
+ while (dataIdx < sorted.length && sorted[dataIdx].timestamp < nextMs) {
231
+ if (sorted[dataIdx].timestamp >= currentMs) {
232
+ itemsInInterval.push(sorted[dataIdx].item);
233
+ }
234
+ dataIdx++;
235
+ }
236
+ dataIdx = startIdx;
237
+ result.push({
238
+ x: new Date(currentMs),
239
+ value: accumulator(itemsInInterval)
240
+ });
241
+ }
242
+ return result;
243
+ }
244
+ /**
245
+ * Creates a count accumulator that returns the number of items.
246
+ *
247
+ * @returns Accumulator function that counts items
248
+ *
249
+ * @example
250
+ * createTimeSeries(orders, start, end, interval, count())
251
+ */
252
+ function count() {
253
+ return (items) => items.length;
254
+ }
255
+ /**
256
+ * Creates a sum accumulator that sums values of a specific field.
257
+ *
258
+ * @param field - Name of the field to sum
259
+ * @returns Accumulator function that sums field values
260
+ *
261
+ * @example
262
+ * createTimeSeries(orders, start, end, interval, sum('total'))
263
+ */
264
+ function sum(field) {
265
+ return (items) => items.reduce((sum, item) => sum + (Number(item[field]) || 0), 0);
266
+ }
267
+ /**
268
+ * Creates an average accumulator that calculates mean of a specific field.
269
+ * Optionally excludes outliers using IQR method (requires at least 3 data points).
270
+ *
271
+ * @param field - Name of the field to average
272
+ * @param options - Optional configuration
273
+ * @param options.excludeOutliers - If true, excludes outliers using IQR method
274
+ * @returns Accumulator function that calculates average
275
+ *
276
+ * @example
277
+ * createTimeSeries(orders, start, end, interval, average('total'))
278
+ * createTimeSeries(orders, start, end, interval, average('total', { excludeOutliers: true }))
279
+ */
280
+ function average(field, options = {}) {
281
+ return (items) => {
282
+ if (items.length === 0)
283
+ return 0;
284
+ const values = items.map(item => Number(item[field]) || 0);
285
+ if (options.excludeOutliers && values.length > 2) {
286
+ const sorted = [...values].sort((a, b) => a - b);
287
+ const q1 = sorted[Math.floor(sorted.length * 0.25)];
288
+ const q3 = sorted[Math.floor(sorted.length * 0.75)];
289
+ const iqr = q3 - q1;
290
+ const filtered = values.filter(v => v >= q1 - 1.5 * iqr && v <= q3 + 1.5 * iqr);
291
+ return filtered.reduce((sum, v) => sum + v, 0) / filtered.length;
292
+ }
293
+ return values.reduce((sum, v) => sum + v, 0) / values.length;
294
+ };
295
+ }
296
+ /**
297
+ * Abstract provider for calculating statistics.
298
+ * Extend this class to implement custom statistics providers.
299
+ */
300
+ class AbstractStatisticsProvider {
301
+ constructor(container) {
302
+ this.container = container;
303
+ this.query = container[utils_1.ContainerRegistrationKeys.QUERY];
304
+ }
305
+ }
306
+ exports.AbstractStatisticsProvider = AbstractStatisticsProvider;
307
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9zdGF0aXN0aWNzL3Byb3ZpZGVycy9wcm92aWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFrT0EsMEJBNkJDO0FBaUJELDhDQWdCQztBQWlCRCw4Q0FXQztBQWVELDRDQWtEQztBQVVELHNCQUVDO0FBV0Qsa0JBRUM7QUFlRCwwQkFvQkM7QUF4YkQscURBQXNFO0FBZ0d0RTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFhLFdBQVc7SUFHcEIsWUFBWSxFQUFVLEVBQUUsSUFBWTtRQUNoQyxJQUFJLENBQUMsU0FBUyxHQUFHO1lBQ2IsRUFBRTtZQUNGLElBQUk7WUFDSixVQUFVLEVBQUU7Z0JBQ1IsTUFBTSxFQUFFLEVBQUU7YUFDYjtZQUNELE9BQU8sRUFBRSxFQUFFO1NBQ2QsQ0FBQztJQUNOLENBQUM7SUFFRDs7T0FFRztJQUNILFdBQVcsQ0FBQyxXQUFtQjtRQUMzQixJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7UUFDekMsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLEtBQStCLEVBQUUsWUFBa0I7UUFDckQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUU3QyxJQUFJLFlBQVksS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUM3QixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ3RDLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7WUFDNUMsQ0FBQztZQUNELElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdB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