@open-mercato/core 0.4.2-canary-10c7a8bf2a → 0.4.2-canary-e6bf6a353e

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 (136) hide show
  1. package/dist/modules/auth/lib/setup-app.js +2 -0
  2. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  3. package/dist/modules/catalog/analytics.js +27 -0
  4. package/dist/modules/catalog/analytics.js.map +7 -0
  5. package/dist/modules/customers/analytics.js +50 -0
  6. package/dist/modules/customers/analytics.js.map +7 -0
  7. package/dist/modules/dashboards/acl.js +2 -1
  8. package/dist/modules/dashboards/acl.js.map +2 -2
  9. package/dist/modules/dashboards/api/widgets/data/route.js +187 -0
  10. package/dist/modules/dashboards/api/widgets/data/route.js.map +7 -0
  11. package/dist/modules/dashboards/cli.js +142 -1
  12. package/dist/modules/dashboards/cli.js.map +2 -2
  13. package/dist/modules/dashboards/di.js +11 -0
  14. package/dist/modules/dashboards/di.js.map +7 -0
  15. package/dist/modules/dashboards/lib/aggregations.js +162 -0
  16. package/dist/modules/dashboards/lib/aggregations.js.map +7 -0
  17. package/dist/modules/dashboards/lib/formatters.js +34 -0
  18. package/dist/modules/dashboards/lib/formatters.js.map +7 -0
  19. package/dist/modules/dashboards/seed/analytics.js +383 -0
  20. package/dist/modules/dashboards/seed/analytics.js.map +7 -0
  21. package/dist/modules/dashboards/services/analyticsRegistry.js +52 -0
  22. package/dist/modules/dashboards/services/analyticsRegistry.js.map +7 -0
  23. package/dist/modules/dashboards/services/widgetDataService.js +207 -0
  24. package/dist/modules/dashboards/services/widgetDataService.js.map +7 -0
  25. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/config.js +18 -0
  26. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/config.js.map +7 -0
  27. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js +128 -0
  28. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js.map +7 -0
  29. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js +25 -0
  30. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js.map +7 -0
  31. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/config.js +18 -0
  32. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/config.js.map +7 -0
  33. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.js +126 -0
  34. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.js.map +7 -0
  35. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js +25 -0
  36. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js.map +7 -0
  37. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/config.js +18 -0
  38. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/config.js.map +7 -0
  39. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js +151 -0
  40. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js.map +7 -0
  41. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js +25 -0
  42. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js.map +7 -0
  43. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/config.js +18 -0
  44. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/config.js.map +7 -0
  45. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.js +126 -0
  46. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.js.map +7 -0
  47. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js +25 -0
  48. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js.map +7 -0
  49. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/config.js +16 -0
  50. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/config.js.map +7 -0
  51. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js +123 -0
  52. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js.map +7 -0
  53. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +25 -0
  54. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +7 -0
  55. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/config.js +18 -0
  56. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/config.js.map +7 -0
  57. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js +128 -0
  58. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js.map +7 -0
  59. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js +25 -0
  60. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js.map +7 -0
  61. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/config.js +21 -0
  62. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/config.js.map +7 -0
  63. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +211 -0
  64. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +7 -0
  65. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js +25 -0
  66. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js.map +7 -0
  67. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/config.js +19 -0
  68. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/config.js.map +7 -0
  69. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +131 -0
  70. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +7 -0
  71. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js +25 -0
  72. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js.map +7 -0
  73. package/dist/modules/dashboards/widgets/dashboard/top-customers/config.js +19 -0
  74. package/dist/modules/dashboards/widgets/dashboard/top-customers/config.js.map +7 -0
  75. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +153 -0
  76. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +7 -0
  77. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js +25 -0
  78. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js.map +7 -0
  79. package/dist/modules/dashboards/widgets/dashboard/top-products/config.js +22 -0
  80. package/dist/modules/dashboards/widgets/dashboard/top-products/config.js.map +7 -0
  81. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +180 -0
  82. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js.map +7 -0
  83. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js +25 -0
  84. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js.map +7 -0
  85. package/dist/modules/sales/analytics.js +67 -0
  86. package/dist/modules/sales/analytics.js.map +7 -0
  87. package/package.json +2 -2
  88. package/src/modules/auth/lib/setup-app.ts +2 -0
  89. package/src/modules/catalog/analytics.ts +24 -0
  90. package/src/modules/customers/analytics.ts +47 -0
  91. package/src/modules/dashboards/acl.ts +1 -0
  92. package/src/modules/dashboards/api/widgets/data/route.ts +221 -0
  93. package/src/modules/dashboards/cli.ts +164 -1
  94. package/src/modules/dashboards/di.ts +9 -0
  95. package/src/modules/dashboards/i18n/de.json +115 -1
  96. package/src/modules/dashboards/i18n/en.json +115 -1
  97. package/src/modules/dashboards/i18n/es.json +115 -1
  98. package/src/modules/dashboards/i18n/pl.json +115 -1
  99. package/src/modules/dashboards/lib/__tests__/aggregations.test.ts +327 -0
  100. package/src/modules/dashboards/lib/__tests__/formatters.test.ts +128 -0
  101. package/src/modules/dashboards/lib/aggregations.ts +225 -0
  102. package/src/modules/dashboards/lib/formatters.ts +36 -0
  103. package/src/modules/dashboards/seed/analytics.ts +405 -0
  104. package/src/modules/dashboards/services/analyticsRegistry.ts +79 -0
  105. package/src/modules/dashboards/services/widgetDataService.ts +329 -0
  106. package/src/modules/dashboards/widgets/dashboard/aov-kpi/config.ts +20 -0
  107. package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.tsx +135 -0
  108. package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.ts +24 -0
  109. package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/config.ts +20 -0
  110. package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.tsx +133 -0
  111. package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.ts +24 -0
  112. package/src/modules/dashboards/widgets/dashboard/orders-by-status/config.ts +20 -0
  113. package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.tsx +154 -0
  114. package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.ts +24 -0
  115. package/src/modules/dashboards/widgets/dashboard/orders-kpi/config.ts +20 -0
  116. package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.tsx +133 -0
  117. package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.ts +24 -0
  118. package/src/modules/dashboards/widgets/dashboard/pipeline-summary/config.ts +17 -0
  119. package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.tsx +137 -0
  120. package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +24 -0
  121. package/src/modules/dashboards/widgets/dashboard/revenue-kpi/config.ts +20 -0
  122. package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.tsx +135 -0
  123. package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.ts +24 -0
  124. package/src/modules/dashboards/widgets/dashboard/revenue-trend/config.ts +24 -0
  125. package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +220 -0
  126. package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.ts +24 -0
  127. package/src/modules/dashboards/widgets/dashboard/sales-by-region/config.ts +21 -0
  128. package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +131 -0
  129. package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.ts +24 -0
  130. package/src/modules/dashboards/widgets/dashboard/top-customers/config.ts +21 -0
  131. package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +161 -0
  132. package/src/modules/dashboards/widgets/dashboard/top-customers/widget.ts +24 -0
  133. package/src/modules/dashboards/widgets/dashboard/top-products/config.ts +27 -0
  134. package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +181 -0
  135. package/src/modules/dashboards/widgets/dashboard/top-products/widget.ts +24 -0
  136. package/src/modules/sales/analytics.ts +64 -0
@@ -0,0 +1,383 @@
1
+ import { randomUUID } from "crypto";
2
+ import {
3
+ SalesOrder,
4
+ SalesOrderLine
5
+ } from "@open-mercato/core/modules/sales/data/entities";
6
+ import {
7
+ CustomerEntity,
8
+ CustomerCompanyProfile,
9
+ CustomerDeal
10
+ } from "@open-mercato/core/modules/customers/data/entities";
11
+ import {
12
+ CatalogProduct,
13
+ CatalogProductVariant
14
+ } from "@open-mercato/core/modules/catalog/data/entities";
15
+ const ORDER_STATUSES = ["draft", "pending", "confirmed", "processing", "shipped", "delivered", "cancelled"];
16
+ const FULFILLMENT_STATUSES = ["pending", "in_fulfillment", "partially_fulfilled", "fulfilled"];
17
+ const PAYMENT_STATUSES = ["unpaid", "partial", "paid", "refunded"];
18
+ const DEAL_PIPELINE_STAGES = ["lead", "qualified", "proposal", "negotiation", "closed_won", "closed_lost"];
19
+ const COUNTRIES = ["US", "GB", "DE", "FR", "CA", "AU", "NL", "ES", "IT", "PL"];
20
+ const REGIONS_BY_COUNTRY = {
21
+ US: ["California", "New York", "Texas", "Florida", "Illinois", "Washington", "Massachusetts"],
22
+ GB: ["England", "Scotland", "Wales"],
23
+ DE: ["Bavaria", "Berlin", "Hamburg", "Hessen"],
24
+ FR: ["\xCEle-de-France", "Provence", "Rh\xF4ne-Alpes"],
25
+ CA: ["Ontario", "Quebec", "British Columbia"],
26
+ AU: ["New South Wales", "Victoria", "Queensland"],
27
+ NL: ["North Holland", "South Holland"],
28
+ ES: ["Madrid", "Catalonia", "Andalusia"],
29
+ IT: ["Lombardy", "Lazio", "Veneto"],
30
+ PL: ["Mazovia", "Lesser Poland", "Silesia"]
31
+ };
32
+ const COMPANY_NAMES = [
33
+ "Acme Corp",
34
+ "Global Industries",
35
+ "Tech Solutions",
36
+ "Prime Services",
37
+ "Northern Analytics",
38
+ "Blue Ocean Trading",
39
+ "Summit Enterprises",
40
+ "Horizon Dynamics",
41
+ "Vertex Systems",
42
+ "Atlas Logistics",
43
+ "Pinnacle Group",
44
+ "Quantum Labs",
45
+ "Stellar Innovations",
46
+ "Pacific Partners",
47
+ "Apex Manufacturing",
48
+ "Nexus Technologies",
49
+ "Eclipse Ventures",
50
+ "Titan Holdings",
51
+ "Vanguard Solutions",
52
+ "Momentum Corp",
53
+ "Crystal Clear Media",
54
+ "Silver Line Transport",
55
+ "Golden Gate Imports",
56
+ "Red Rock Mining",
57
+ "Green Valley Foods",
58
+ "Blue Sky Aviation",
59
+ "White Mountain Retail",
60
+ "Black Diamond Sports"
61
+ ];
62
+ const PRODUCT_NAMES = [
63
+ "Premium Widget",
64
+ "Standard Component",
65
+ "Professional Kit",
66
+ "Enterprise Module",
67
+ "Basic Starter Pack",
68
+ "Advanced System",
69
+ "Deluxe Bundle",
70
+ "Essential Tools",
71
+ "Pro Series Device",
72
+ "Ultra Performance Unit",
73
+ "Classic Edition",
74
+ "Limited Series",
75
+ "Industrial Grade Part",
76
+ "Consumer Package",
77
+ "Business Solution",
78
+ "Home Edition"
79
+ ];
80
+ const DEAL_TITLES = [
81
+ "Enterprise License Deal",
82
+ "Annual Subscription",
83
+ "Pilot Program",
84
+ "Strategic Partnership",
85
+ "Volume Purchase Agreement",
86
+ "Service Contract",
87
+ "Implementation Project",
88
+ "Expansion Deal",
89
+ "Renewal Opportunity",
90
+ "Upsell Initiative",
91
+ "Cross-sell Package",
92
+ "Custom Solution"
93
+ ];
94
+ function randomInt(min, max) {
95
+ return Math.floor(Math.random() * (max - min + 1)) + min;
96
+ }
97
+ function randomFloat(min, max, decimals = 2) {
98
+ const value = Math.random() * (max - min) + min;
99
+ return Number(value.toFixed(decimals));
100
+ }
101
+ function randomElement(arr) {
102
+ return arr[Math.floor(Math.random() * arr.length)];
103
+ }
104
+ function randomElements(arr, count) {
105
+ const shuffled = [...arr].sort(() => Math.random() - 0.5);
106
+ return shuffled.slice(0, Math.min(count, arr.length));
107
+ }
108
+ function toAmount(value) {
109
+ return value.toFixed(2);
110
+ }
111
+ function daysAgo(days) {
112
+ const date = /* @__PURE__ */ new Date();
113
+ date.setDate(date.getDate() - days);
114
+ return date;
115
+ }
116
+ function randomDateInRange(startDaysAgo, endDaysAgo) {
117
+ const daysOffset = randomInt(endDaysAgo, startDaysAgo);
118
+ return daysAgo(daysOffset);
119
+ }
120
+ function generateOrderNumber(index) {
121
+ return `SO-ANALYTICS-${String(index).padStart(5, "0")}`;
122
+ }
123
+ async function seedAnalyticsData(em, scope, options = {}) {
124
+ const {
125
+ months = 6,
126
+ ordersPerMonth = 50,
127
+ customersCount = 25,
128
+ productsCount = 15,
129
+ dealsCount = 20
130
+ } = options;
131
+ const existingOrders = await em.count(SalesOrder, {
132
+ tenantId: scope.tenantId,
133
+ organizationId: scope.organizationId,
134
+ orderNumber: { $like: "SO-ANALYTICS-%" }
135
+ });
136
+ if (existingOrders > 0) {
137
+ return { orders: 0, customers: 0, products: 0, deals: 0 };
138
+ }
139
+ const customers = [];
140
+ const products = [];
141
+ const variants = [];
142
+ for (let i = 0; i < customersCount; i++) {
143
+ const companyName = COMPANY_NAMES[i % COMPANY_NAMES.length];
144
+ const customerCreatedAt = randomDateInRange(months * 30 + 60, 0);
145
+ const customer = em.create(CustomerEntity, {
146
+ id: randomUUID(),
147
+ organizationId: scope.organizationId,
148
+ tenantId: scope.tenantId,
149
+ kind: "company",
150
+ displayName: `${companyName} #${i + 1}`,
151
+ primaryEmail: `contact${i + 1}@${companyName.toLowerCase().replace(/\s+/g, "")}.example.com`,
152
+ status: "active",
153
+ lifecycleStage: randomElement(["lead", "customer", "opportunity"]),
154
+ isActive: true,
155
+ createdAt: customerCreatedAt,
156
+ updatedAt: customerCreatedAt
157
+ });
158
+ em.persist(customer);
159
+ customers.push(customer);
160
+ const companyProfile = em.create(CustomerCompanyProfile, {
161
+ id: randomUUID(),
162
+ organizationId: scope.organizationId,
163
+ tenantId: scope.tenantId,
164
+ entity: customer,
165
+ legalName: `${companyName} Inc.`,
166
+ brandName: companyName,
167
+ industry: randomElement(["Technology", "Manufacturing", "Retail", "Services", "Healthcare"]),
168
+ sizeBucket: randomElement(["small", "medium", "large", "enterprise"]),
169
+ annualRevenue: toAmount(randomFloat(1e5, 5e7)),
170
+ createdAt: customerCreatedAt,
171
+ updatedAt: customerCreatedAt
172
+ });
173
+ em.persist(companyProfile);
174
+ }
175
+ for (let i = 0; i < productsCount; i++) {
176
+ const productName = PRODUCT_NAMES[i % PRODUCT_NAMES.length];
177
+ const productCreatedAt = daysAgo(months * 30 + randomInt(0, 30));
178
+ const product = em.create(CatalogProduct, {
179
+ id: randomUUID(),
180
+ organizationId: scope.organizationId,
181
+ tenantId: scope.tenantId,
182
+ title: `${productName} ${i + 1}`,
183
+ handle: `analytics-product-${i + 1}`,
184
+ sku: `SKU-ANALYTICS-${String(i + 1).padStart(3, "0")}`,
185
+ productType: "simple",
186
+ isConfigurable: false,
187
+ isActive: true,
188
+ createdAt: productCreatedAt,
189
+ updatedAt: productCreatedAt
190
+ });
191
+ em.persist(product);
192
+ products.push(product);
193
+ const variant = em.create(CatalogProductVariant, {
194
+ id: randomUUID(),
195
+ organizationId: scope.organizationId,
196
+ tenantId: scope.tenantId,
197
+ product,
198
+ name: "Default",
199
+ sku: `${product.sku}-DEFAULT`,
200
+ isDefault: true,
201
+ isActive: true,
202
+ createdAt: productCreatedAt,
203
+ updatedAt: productCreatedAt
204
+ });
205
+ em.persist(variant);
206
+ variants.push(variant);
207
+ }
208
+ let orderIndex = 1;
209
+ const totalDays = months * 30;
210
+ const orders = [];
211
+ for (let dayOffset = totalDays; dayOffset >= 0; dayOffset--) {
212
+ const ordersToday = Math.round(ordersPerMonth / 30 * randomFloat(0.5, 1.5));
213
+ for (let j = 0; j < ordersToday; j++) {
214
+ const orderDate = daysAgo(dayOffset);
215
+ const customer = randomElement(customers);
216
+ const country = randomElement(COUNTRIES);
217
+ const region = randomElement(REGIONS_BY_COUNTRY[country] || [""]);
218
+ const lineCount = randomInt(1, 5);
219
+ const selectedProducts = randomElements(products, lineCount);
220
+ let subtotalNet = 0;
221
+ let subtotalGross = 0;
222
+ let taxTotal = 0;
223
+ const orderLines = [];
224
+ for (let k = 0; k < selectedProducts.length; k++) {
225
+ const product = selectedProducts[k];
226
+ const variant = variants.find((v) => v.product.id === product.id) || variants[0];
227
+ const quantity = randomInt(1, 10);
228
+ const unitPriceNet = randomFloat(10, 500);
229
+ const taxRate = randomElement([0, 5, 10, 20, 23]);
230
+ const unitPriceGross = unitPriceNet * (1 + taxRate / 100);
231
+ const lineNetAmount = unitPriceNet * quantity;
232
+ const lineGrossAmount = unitPriceGross * quantity;
233
+ const lineTaxAmount = lineGrossAmount - lineNetAmount;
234
+ subtotalNet += lineNetAmount;
235
+ subtotalGross += lineGrossAmount;
236
+ taxTotal += lineTaxAmount;
237
+ orderLines.push({
238
+ product,
239
+ variant,
240
+ quantity,
241
+ unitPriceNet,
242
+ unitPriceGross,
243
+ taxRate,
244
+ lineNetAmount,
245
+ lineGrossAmount,
246
+ lineTaxAmount
247
+ });
248
+ }
249
+ const order = em.create(SalesOrder, {
250
+ id: randomUUID(),
251
+ organizationId: scope.organizationId,
252
+ tenantId: scope.tenantId,
253
+ orderNumber: generateOrderNumber(orderIndex++),
254
+ status: randomElement(ORDER_STATUSES),
255
+ fulfillmentStatus: randomElement(FULFILLMENT_STATUSES),
256
+ paymentStatus: randomElement(PAYMENT_STATUSES),
257
+ customerEntityId: customer.id,
258
+ customerSnapshot: {
259
+ customer: {
260
+ id: customer.id,
261
+ kind: customer.kind,
262
+ displayName: customer.displayName
263
+ }
264
+ },
265
+ currencyCode: "USD",
266
+ placedAt: orderDate,
267
+ shippingAddressSnapshot: {
268
+ country,
269
+ region,
270
+ city: `City ${randomInt(1, 100)}`,
271
+ postalCode: String(randomInt(1e4, 99999))
272
+ },
273
+ billingAddressSnapshot: {
274
+ country,
275
+ region,
276
+ city: `City ${randomInt(1, 100)}`,
277
+ postalCode: String(randomInt(1e4, 99999))
278
+ },
279
+ subtotalNetAmount: toAmount(subtotalNet),
280
+ subtotalGrossAmount: toAmount(subtotalGross),
281
+ discountTotalAmount: "0.00",
282
+ taxTotalAmount: toAmount(taxTotal),
283
+ shippingNetAmount: "0.00",
284
+ shippingGrossAmount: "0.00",
285
+ surchargeTotalAmount: "0.00",
286
+ grandTotalNetAmount: toAmount(subtotalNet),
287
+ grandTotalGrossAmount: toAmount(subtotalGross),
288
+ paidTotalAmount: "0.00",
289
+ refundedTotalAmount: "0.00",
290
+ outstandingAmount: toAmount(subtotalGross),
291
+ lineItemCount: orderLines.length,
292
+ metadata: { seed: "dashboards.analytics" },
293
+ createdAt: orderDate,
294
+ updatedAt: orderDate
295
+ });
296
+ em.persist(order);
297
+ orders.push(order);
298
+ for (let k = 0; k < orderLines.length; k++) {
299
+ const lineData = orderLines[k];
300
+ const line = em.create(SalesOrderLine, {
301
+ id: randomUUID(),
302
+ order,
303
+ organizationId: scope.organizationId,
304
+ tenantId: scope.tenantId,
305
+ lineNumber: k + 1,
306
+ kind: "product",
307
+ name: lineData.product.title,
308
+ quantity: toAmount(lineData.quantity),
309
+ currencyCode: "USD",
310
+ unitPriceNet: toAmount(lineData.unitPriceNet),
311
+ unitPriceGross: toAmount(lineData.unitPriceGross),
312
+ discountAmount: "0.00",
313
+ discountPercent: "0.00",
314
+ taxRate: toAmount(lineData.taxRate),
315
+ taxAmount: toAmount(lineData.lineTaxAmount),
316
+ totalNetAmount: toAmount(lineData.lineNetAmount),
317
+ totalGrossAmount: toAmount(lineData.lineGrossAmount),
318
+ reservedQuantity: "0",
319
+ fulfilledQuantity: "0",
320
+ invoicedQuantity: "0",
321
+ returnedQuantity: "0",
322
+ productId: lineData.product.id,
323
+ productVariantId: lineData.variant?.id ?? null,
324
+ catalogSnapshot: {
325
+ product: {
326
+ id: lineData.product.id,
327
+ title: lineData.product.title,
328
+ sku: lineData.product.sku
329
+ },
330
+ variant: lineData.variant ? {
331
+ id: lineData.variant.id,
332
+ name: lineData.variant.name,
333
+ sku: lineData.variant.sku
334
+ } : null
335
+ },
336
+ createdAt: orderDate,
337
+ updatedAt: orderDate
338
+ });
339
+ em.persist(line);
340
+ }
341
+ }
342
+ }
343
+ for (let i = 0; i < dealsCount; i++) {
344
+ const customer = randomElement(customers);
345
+ const dealCreatedAt = randomDateInRange(months * 30, 0);
346
+ const pipelineStage = randomElement(DEAL_PIPELINE_STAGES);
347
+ const probabilityByStage = {
348
+ lead: 10,
349
+ qualified: 25,
350
+ proposal: 50,
351
+ negotiation: 75,
352
+ closed_won: 100,
353
+ closed_lost: 0
354
+ };
355
+ const deal = em.create(CustomerDeal, {
356
+ id: randomUUID(),
357
+ organizationId: scope.organizationId,
358
+ tenantId: scope.tenantId,
359
+ title: `${randomElement(DEAL_TITLES)} - ${customer.displayName}`,
360
+ status: pipelineStage === "closed_won" || pipelineStage === "closed_lost" ? "closed" : "open",
361
+ pipelineStage,
362
+ valueAmount: toAmount(randomFloat(5e3, 5e5)),
363
+ valueCurrency: "USD",
364
+ probability: probabilityByStage[pipelineStage],
365
+ expectedCloseAt: daysAgo(randomInt(-60, 90)),
366
+ source: randomElement(["inbound", "outbound", "referral", "partner"]),
367
+ createdAt: dealCreatedAt,
368
+ updatedAt: dealCreatedAt
369
+ });
370
+ em.persist(deal);
371
+ }
372
+ await em.flush();
373
+ return {
374
+ orders: orders.length,
375
+ customers: customers.length,
376
+ products: products.length,
377
+ deals: dealsCount
378
+ };
379
+ }
380
+ export {
381
+ seedAnalyticsData
382
+ };
383
+ //# sourceMappingURL=analytics.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/dashboards/seed/analytics.ts"],
4
+ "sourcesContent": ["import { randomUUID } from 'crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n SalesOrder,\n SalesOrderLine,\n} from '@open-mercato/core/modules/sales/data/entities'\nimport {\n CustomerEntity,\n CustomerCompanyProfile,\n CustomerDeal,\n} from '@open-mercato/core/modules/customers/data/entities'\nimport {\n CatalogProduct,\n CatalogProductVariant,\n} from '@open-mercato/core/modules/catalog/data/entities'\n\nexport type AnalyticsSeedScope = {\n tenantId: string\n organizationId: string\n}\n\nexport type AnalyticsSeedOptions = {\n months?: number\n ordersPerMonth?: number\n customersCount?: number\n productsCount?: number\n dealsCount?: number\n}\n\nconst ORDER_STATUSES = ['draft', 'pending', 'confirmed', 'processing', 'shipped', 'delivered', 'cancelled'] as const\nconst FULFILLMENT_STATUSES = ['pending', 'in_fulfillment', 'partially_fulfilled', 'fulfilled'] as const\nconst PAYMENT_STATUSES = ['unpaid', 'partial', 'paid', 'refunded'] as const\nconst DEAL_PIPELINE_STAGES = ['lead', 'qualified', 'proposal', 'negotiation', 'closed_won', 'closed_lost'] as const\nconst COUNTRIES = ['US', 'GB', 'DE', 'FR', 'CA', 'AU', 'NL', 'ES', 'IT', 'PL'] as const\nconst REGIONS_BY_COUNTRY: Record<string, string[]> = {\n US: ['California', 'New York', 'Texas', 'Florida', 'Illinois', 'Washington', 'Massachusetts'],\n GB: ['England', 'Scotland', 'Wales'],\n DE: ['Bavaria', 'Berlin', 'Hamburg', 'Hessen'],\n FR: ['\u00CEle-de-France', 'Provence', 'Rh\u00F4ne-Alpes'],\n CA: ['Ontario', 'Quebec', 'British Columbia'],\n AU: ['New South Wales', 'Victoria', 'Queensland'],\n NL: ['North Holland', 'South Holland'],\n ES: ['Madrid', 'Catalonia', 'Andalusia'],\n IT: ['Lombardy', 'Lazio', 'Veneto'],\n PL: ['Mazovia', 'Lesser Poland', 'Silesia'],\n}\n\nconst COMPANY_NAMES = [\n 'Acme Corp', 'Global Industries', 'Tech Solutions', 'Prime Services',\n 'Northern Analytics', 'Blue Ocean Trading', 'Summit Enterprises', 'Horizon Dynamics',\n 'Vertex Systems', 'Atlas Logistics', 'Pinnacle Group', 'Quantum Labs',\n 'Stellar Innovations', 'Pacific Partners', 'Apex Manufacturing', 'Nexus Technologies',\n 'Eclipse Ventures', 'Titan Holdings', 'Vanguard Solutions', 'Momentum Corp',\n 'Crystal Clear Media', 'Silver Line Transport', 'Golden Gate Imports', 'Red Rock Mining',\n 'Green Valley Foods', 'Blue Sky Aviation', 'White Mountain Retail', 'Black Diamond Sports',\n]\n\nconst PRODUCT_NAMES = [\n 'Premium Widget', 'Standard Component', 'Professional Kit', 'Enterprise Module',\n 'Basic Starter Pack', 'Advanced System', 'Deluxe Bundle', 'Essential Tools',\n 'Pro Series Device', 'Ultra Performance Unit', 'Classic Edition', 'Limited Series',\n 'Industrial Grade Part', 'Consumer Package', 'Business Solution', 'Home Edition',\n]\n\nconst DEAL_TITLES = [\n 'Enterprise License Deal', 'Annual Subscription', 'Pilot Program', 'Strategic Partnership',\n 'Volume Purchase Agreement', 'Service Contract', 'Implementation Project', 'Expansion Deal',\n 'Renewal Opportunity', 'Upsell Initiative', 'Cross-sell Package', 'Custom Solution',\n]\n\nfunction randomInt(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min\n}\n\nfunction randomFloat(min: number, max: number, decimals = 2): number {\n const value = Math.random() * (max - min) + min\n return Number(value.toFixed(decimals))\n}\n\nfunction randomElement<T>(arr: readonly T[]): T {\n return arr[Math.floor(Math.random() * arr.length)]\n}\n\nfunction randomElements<T>(arr: readonly T[], count: number): T[] {\n const shuffled = [...arr].sort(() => Math.random() - 0.5)\n return shuffled.slice(0, Math.min(count, arr.length))\n}\n\nfunction toAmount(value: number): string {\n return value.toFixed(2)\n}\n\nfunction daysAgo(days: number): Date {\n const date = new Date()\n date.setDate(date.getDate() - days)\n return date\n}\n\nfunction randomDateInRange(startDaysAgo: number, endDaysAgo: number): Date {\n const daysOffset = randomInt(endDaysAgo, startDaysAgo)\n return daysAgo(daysOffset)\n}\n\nfunction generateOrderNumber(index: number): string {\n return `SO-ANALYTICS-${String(index).padStart(5, '0')}`\n}\n\nexport async function seedAnalyticsData(\n em: EntityManager,\n scope: AnalyticsSeedScope,\n options: AnalyticsSeedOptions = {}\n): Promise<{ orders: number; customers: number; products: number; deals: number }> {\n const {\n months = 6,\n ordersPerMonth = 50,\n customersCount = 25,\n productsCount = 15,\n dealsCount = 20,\n } = options\n\n const existingOrders = await em.count(SalesOrder, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n orderNumber: { $like: 'SO-ANALYTICS-%' },\n })\n\n if (existingOrders > 0) {\n return { orders: 0, customers: 0, products: 0, deals: 0 }\n }\n\n const customers: CustomerEntity[] = []\n const products: CatalogProduct[] = []\n const variants: CatalogProductVariant[] = []\n\n for (let i = 0; i < customersCount; i++) {\n const companyName = COMPANY_NAMES[i % COMPANY_NAMES.length]\n const customerCreatedAt = randomDateInRange(months * 30 + 60, 0)\n\n const customer = em.create(CustomerEntity, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n kind: 'company',\n displayName: `${companyName} #${i + 1}`,\n primaryEmail: `contact${i + 1}@${companyName.toLowerCase().replace(/\\s+/g, '')}.example.com`,\n status: 'active',\n lifecycleStage: randomElement(['lead', 'customer', 'opportunity']),\n isActive: true,\n createdAt: customerCreatedAt,\n updatedAt: customerCreatedAt,\n })\n em.persist(customer)\n customers.push(customer)\n\n const companyProfile = em.create(CustomerCompanyProfile, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n entity: customer,\n legalName: `${companyName} Inc.`,\n brandName: companyName,\n industry: randomElement(['Technology', 'Manufacturing', 'Retail', 'Services', 'Healthcare']),\n sizeBucket: randomElement(['small', 'medium', 'large', 'enterprise']),\n annualRevenue: toAmount(randomFloat(100000, 50000000)),\n createdAt: customerCreatedAt,\n updatedAt: customerCreatedAt,\n })\n em.persist(companyProfile)\n }\n\n for (let i = 0; i < productsCount; i++) {\n const productName = PRODUCT_NAMES[i % PRODUCT_NAMES.length]\n const productCreatedAt = daysAgo(months * 30 + randomInt(0, 30))\n\n const product = em.create(CatalogProduct, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n title: `${productName} ${i + 1}`,\n handle: `analytics-product-${i + 1}`,\n sku: `SKU-ANALYTICS-${String(i + 1).padStart(3, '0')}`,\n productType: 'simple',\n isConfigurable: false,\n isActive: true,\n createdAt: productCreatedAt,\n updatedAt: productCreatedAt,\n })\n em.persist(product)\n products.push(product)\n\n const variant = em.create(CatalogProductVariant, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n product,\n name: 'Default',\n sku: `${product.sku}-DEFAULT`,\n isDefault: true,\n isActive: true,\n createdAt: productCreatedAt,\n updatedAt: productCreatedAt,\n })\n em.persist(variant)\n variants.push(variant)\n }\n\n let orderIndex = 1\n const totalDays = months * 30\n const orders: SalesOrder[] = []\n\n for (let dayOffset = totalDays; dayOffset >= 0; dayOffset--) {\n const ordersToday = Math.round(ordersPerMonth / 30 * randomFloat(0.5, 1.5))\n\n for (let j = 0; j < ordersToday; j++) {\n const orderDate = daysAgo(dayOffset)\n const customer = randomElement(customers)\n const country = randomElement(COUNTRIES)\n const region = randomElement(REGIONS_BY_COUNTRY[country] || [''])\n\n const lineCount = randomInt(1, 5)\n const selectedProducts = randomElements(products, lineCount)\n\n let subtotalNet = 0\n let subtotalGross = 0\n let taxTotal = 0\n\n const orderLines: Array<{\n product: CatalogProduct\n variant: CatalogProductVariant\n quantity: number\n unitPriceNet: number\n unitPriceGross: number\n taxRate: number\n lineNetAmount: number\n lineGrossAmount: number\n lineTaxAmount: number\n }> = []\n\n for (let k = 0; k < selectedProducts.length; k++) {\n const product = selectedProducts[k]\n const variant = variants.find((v) => v.product.id === product.id) || variants[0]\n const quantity = randomInt(1, 10)\n const unitPriceNet = randomFloat(10, 500)\n const taxRate = randomElement([0, 5, 10, 20, 23])\n const unitPriceGross = unitPriceNet * (1 + taxRate / 100)\n const lineNetAmount = unitPriceNet * quantity\n const lineGrossAmount = unitPriceGross * quantity\n const lineTaxAmount = lineGrossAmount - lineNetAmount\n\n subtotalNet += lineNetAmount\n subtotalGross += lineGrossAmount\n taxTotal += lineTaxAmount\n\n orderLines.push({\n product,\n variant,\n quantity,\n unitPriceNet,\n unitPriceGross,\n taxRate,\n lineNetAmount,\n lineGrossAmount,\n lineTaxAmount,\n })\n }\n\n const order = em.create(SalesOrder, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n orderNumber: generateOrderNumber(orderIndex++),\n status: randomElement(ORDER_STATUSES),\n fulfillmentStatus: randomElement(FULFILLMENT_STATUSES),\n paymentStatus: randomElement(PAYMENT_STATUSES),\n customerEntityId: customer.id,\n customerSnapshot: {\n customer: {\n id: customer.id,\n kind: customer.kind,\n displayName: customer.displayName,\n },\n },\n currencyCode: 'USD',\n placedAt: orderDate,\n shippingAddressSnapshot: {\n country,\n region,\n city: `City ${randomInt(1, 100)}`,\n postalCode: String(randomInt(10000, 99999)),\n },\n billingAddressSnapshot: {\n country,\n region,\n city: `City ${randomInt(1, 100)}`,\n postalCode: String(randomInt(10000, 99999)),\n },\n subtotalNetAmount: toAmount(subtotalNet),\n subtotalGrossAmount: toAmount(subtotalGross),\n discountTotalAmount: '0.00',\n taxTotalAmount: toAmount(taxTotal),\n shippingNetAmount: '0.00',\n shippingGrossAmount: '0.00',\n surchargeTotalAmount: '0.00',\n grandTotalNetAmount: toAmount(subtotalNet),\n grandTotalGrossAmount: toAmount(subtotalGross),\n paidTotalAmount: '0.00',\n refundedTotalAmount: '0.00',\n outstandingAmount: toAmount(subtotalGross),\n lineItemCount: orderLines.length,\n metadata: { seed: 'dashboards.analytics' },\n createdAt: orderDate,\n updatedAt: orderDate,\n })\n em.persist(order)\n orders.push(order)\n\n for (let k = 0; k < orderLines.length; k++) {\n const lineData = orderLines[k]\n const line = em.create(SalesOrderLine, {\n id: randomUUID(),\n order,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n lineNumber: k + 1,\n kind: 'product',\n name: lineData.product.title,\n quantity: toAmount(lineData.quantity),\n currencyCode: 'USD',\n unitPriceNet: toAmount(lineData.unitPriceNet),\n unitPriceGross: toAmount(lineData.unitPriceGross),\n discountAmount: '0.00',\n discountPercent: '0.00',\n taxRate: toAmount(lineData.taxRate),\n taxAmount: toAmount(lineData.lineTaxAmount),\n totalNetAmount: toAmount(lineData.lineNetAmount),\n totalGrossAmount: toAmount(lineData.lineGrossAmount),\n reservedQuantity: '0',\n fulfilledQuantity: '0',\n invoicedQuantity: '0',\n returnedQuantity: '0',\n productId: lineData.product.id,\n productVariantId: lineData.variant?.id ?? null,\n catalogSnapshot: {\n product: {\n id: lineData.product.id,\n title: lineData.product.title,\n sku: lineData.product.sku,\n },\n variant: lineData.variant\n ? {\n id: lineData.variant.id,\n name: lineData.variant.name,\n sku: lineData.variant.sku,\n }\n : null,\n },\n createdAt: orderDate,\n updatedAt: orderDate,\n })\n em.persist(line)\n }\n }\n }\n\n for (let i = 0; i < dealsCount; i++) {\n const customer = randomElement(customers)\n const dealCreatedAt = randomDateInRange(months * 30, 0)\n const pipelineStage = randomElement(DEAL_PIPELINE_STAGES)\n\n const probabilityByStage: Record<string, number> = {\n lead: 10,\n qualified: 25,\n proposal: 50,\n negotiation: 75,\n closed_won: 100,\n closed_lost: 0,\n }\n\n const deal = em.create(CustomerDeal, {\n id: randomUUID(),\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n title: `${randomElement(DEAL_TITLES)} - ${customer.displayName}`,\n status: pipelineStage === 'closed_won' || pipelineStage === 'closed_lost' ? 'closed' : 'open',\n pipelineStage,\n valueAmount: toAmount(randomFloat(5000, 500000)),\n valueCurrency: 'USD',\n probability: probabilityByStage[pipelineStage],\n expectedCloseAt: daysAgo(randomInt(-60, 90)),\n source: randomElement(['inbound', 'outbound', 'referral', 'partner']),\n createdAt: dealCreatedAt,\n updatedAt: dealCreatedAt,\n })\n em.persist(deal)\n }\n\n await em.flush()\n\n return {\n orders: orders.length,\n customers: customers.length,\n products: products.length,\n deals: dealsCount,\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,52 @@
1
+ import { getAnalyticsModuleConfigs } from "@open-mercato/shared/modules/analytics";
2
+ class DefaultAnalyticsRegistry {
3
+ constructor(configs) {
4
+ this.configs = configs ?? getAnalyticsModuleConfigs();
5
+ this.entityConfigMap = /* @__PURE__ */ new Map();
6
+ this.buildEntityConfigMap();
7
+ }
8
+ buildEntityConfigMap() {
9
+ for (const moduleConfig of this.configs) {
10
+ for (const entityConfig of moduleConfig.entities) {
11
+ this.entityConfigMap.set(entityConfig.entityId, entityConfig);
12
+ }
13
+ }
14
+ }
15
+ getAllEntityConfigs() {
16
+ return Array.from(this.entityConfigMap.values());
17
+ }
18
+ getEntityConfig(entityId) {
19
+ return this.entityConfigMap.get(entityId) ?? null;
20
+ }
21
+ isValidEntityType(entityId) {
22
+ return this.entityConfigMap.has(entityId);
23
+ }
24
+ getEntityTypeConfig(entityId) {
25
+ const config = this.getEntityConfig(entityId);
26
+ return config?.entityConfig ?? null;
27
+ }
28
+ getFieldMapping(entityId, field) {
29
+ const config = this.getEntityConfig(entityId);
30
+ return config?.fieldMappings[field] ?? null;
31
+ }
32
+ getRequiredFeatures(entityId) {
33
+ const config = this.getEntityConfig(entityId);
34
+ return config?.requiredFeatures ?? null;
35
+ }
36
+ getLabelResolverConfig(entityId, field) {
37
+ const config = this.getEntityConfig(entityId);
38
+ return config?.labelResolvers?.[field] ?? null;
39
+ }
40
+ getAllFieldMappings(entityId) {
41
+ const config = this.getEntityConfig(entityId);
42
+ return config?.fieldMappings ?? null;
43
+ }
44
+ }
45
+ function createAnalyticsRegistry(configs) {
46
+ return new DefaultAnalyticsRegistry(configs);
47
+ }
48
+ export {
49
+ DefaultAnalyticsRegistry,
50
+ createAnalyticsRegistry
51
+ };
52
+ //# sourceMappingURL=analyticsRegistry.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/dashboards/services/analyticsRegistry.ts"],
4
+ "sourcesContent": ["import type {\n AnalyticsEntityConfig,\n AnalyticsEntityTypeConfig,\n AnalyticsFieldMapping,\n AnalyticsLabelResolverConfig,\n AnalyticsModuleConfig,\n} from '@open-mercato/shared/modules/analytics'\nimport { getAnalyticsModuleConfigs } from '@open-mercato/shared/modules/analytics'\n\nexport interface AnalyticsRegistry {\n getAllEntityConfigs(): AnalyticsEntityConfig[]\n getEntityConfig(entityId: string): AnalyticsEntityConfig | null\n isValidEntityType(entityId: string): boolean\n getEntityTypeConfig(entityId: string): AnalyticsEntityTypeConfig | null\n getFieldMapping(entityId: string, field: string): AnalyticsFieldMapping | null\n getRequiredFeatures(entityId: string): string[] | null\n getLabelResolverConfig(entityId: string, field: string): AnalyticsLabelResolverConfig | null\n getAllFieldMappings(entityId: string): Record<string, AnalyticsFieldMapping> | null\n}\n\nexport class DefaultAnalyticsRegistry implements AnalyticsRegistry {\n private configs: AnalyticsModuleConfig[]\n private entityConfigMap: Map<string, AnalyticsEntityConfig>\n\n constructor(configs?: AnalyticsModuleConfig[]) {\n this.configs = configs ?? getAnalyticsModuleConfigs()\n this.entityConfigMap = new Map()\n this.buildEntityConfigMap()\n }\n\n private buildEntityConfigMap(): void {\n for (const moduleConfig of this.configs) {\n for (const entityConfig of moduleConfig.entities) {\n this.entityConfigMap.set(entityConfig.entityId, entityConfig)\n }\n }\n }\n\n getAllEntityConfigs(): AnalyticsEntityConfig[] {\n return Array.from(this.entityConfigMap.values())\n }\n\n getEntityConfig(entityId: string): AnalyticsEntityConfig | null {\n return this.entityConfigMap.get(entityId) ?? null\n }\n\n isValidEntityType(entityId: string): boolean {\n return this.entityConfigMap.has(entityId)\n }\n\n getEntityTypeConfig(entityId: string): AnalyticsEntityTypeConfig | null {\n const config = this.getEntityConfig(entityId)\n return config?.entityConfig ?? null\n }\n\n getFieldMapping(entityId: string, field: string): AnalyticsFieldMapping | null {\n const config = this.getEntityConfig(entityId)\n return config?.fieldMappings[field] ?? null\n }\n\n getRequiredFeatures(entityId: string): string[] | null {\n const config = this.getEntityConfig(entityId)\n return config?.requiredFeatures ?? null\n }\n\n getLabelResolverConfig(entityId: string, field: string): AnalyticsLabelResolverConfig | null {\n const config = this.getEntityConfig(entityId)\n return config?.labelResolvers?.[field] ?? null\n }\n\n getAllFieldMappings(entityId: string): Record<string, AnalyticsFieldMapping> | null {\n const config = this.getEntityConfig(entityId)\n return config?.fieldMappings ?? null\n }\n}\n\nexport function createAnalyticsRegistry(configs?: AnalyticsModuleConfig[]): AnalyticsRegistry {\n return new DefaultAnalyticsRegistry(configs)\n}\n"],
5
+ "mappings": "AAOA,SAAS,iCAAiC;AAanC,MAAM,yBAAsD;AAAA,EAIjE,YAAY,SAAmC;AAC7C,SAAK,UAAU,WAAW,0BAA0B;AACpD,SAAK,kBAAkB,oBAAI,IAAI;AAC/B,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEQ,uBAA6B;AACnC,eAAW,gBAAgB,KAAK,SAAS;AACvC,iBAAW,gBAAgB,aAAa,UAAU;AAChD,aAAK,gBAAgB,IAAI,aAAa,UAAU,YAAY;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAAA,EAEA,sBAA+C;AAC7C,WAAO,MAAM,KAAK,KAAK,gBAAgB,OAAO,CAAC;AAAA,EACjD;AAAA,EAEA,gBAAgB,UAAgD;AAC9D,WAAO,KAAK,gBAAgB,IAAI,QAAQ,KAAK;AAAA,EAC/C;AAAA,EAEA,kBAAkB,UAA2B;AAC3C,WAAO,KAAK,gBAAgB,IAAI,QAAQ;AAAA,EAC1C;AAAA,EAEA,oBAAoB,UAAoD;AACtE,UAAM,SAAS,KAAK,gBAAgB,QAAQ;AAC5C,WAAO,QAAQ,gBAAgB;AAAA,EACjC;AAAA,EAEA,gBAAgB,UAAkB,OAA6C;AAC7E,UAAM,SAAS,KAAK,gBAAgB,QAAQ;AAC5C,WAAO,QAAQ,cAAc,KAAK,KAAK;AAAA,EACzC;AAAA,EAEA,oBAAoB,UAAmC;AACrD,UAAM,SAAS,KAAK,gBAAgB,QAAQ;AAC5C,WAAO,QAAQ,oBAAoB;AAAA,EACrC;AAAA,EAEA,uBAAuB,UAAkB,OAAoD;AAC3F,UAAM,SAAS,KAAK,gBAAgB,QAAQ;AAC5C,WAAO,QAAQ,iBAAiB,KAAK,KAAK;AAAA,EAC5C;AAAA,EAEA,oBAAoB,UAAgE;AAClF,UAAM,SAAS,KAAK,gBAAgB,QAAQ;AAC5C,WAAO,QAAQ,iBAAiB;AAAA,EAClC;AACF;AAEO,SAAS,wBAAwB,SAAsD;AAC5F,SAAO,IAAI,yBAAyB,OAAO;AAC7C;",
6
+ "names": []
7
+ }