@antelopejs/dms-marketing 0.2.2

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 (308) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +143 -0
  3. package/dist/config.d.ts +13 -0
  4. package/dist/config.js +35 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/data-api/body.d.ts +1 -0
  7. package/dist/data-api/body.js +15 -0
  8. package/dist/data-api/body.js.map +1 -0
  9. package/dist/data-api/funnels.d.ts +32 -0
  10. package/dist/data-api/funnels.js +302 -0
  11. package/dist/data-api/funnels.js.map +1 -0
  12. package/dist/data-api/hidden-filter.d.ts +1 -0
  13. package/dist/data-api/hidden-filter.js +11 -0
  14. package/dist/data-api/hidden-filter.js.map +1 -0
  15. package/dist/data-api/index.d.ts +4 -0
  16. package/dist/data-api/index.js +21 -0
  17. package/dist/data-api/index.js.map +1 -0
  18. package/dist/data-api/tenant-scope.d.ts +15 -0
  19. package/dist/data-api/tenant-scope.js +43 -0
  20. package/dist/data-api/tenant-scope.js.map +1 -0
  21. package/dist/data-api/websites.d.ts +25 -0
  22. package/dist/data-api/websites.js +73 -0
  23. package/dist/data-api/websites.js.map +1 -0
  24. package/dist/db/index.d.ts +2 -0
  25. package/dist/db/index.js +19 -0
  26. package/dist/db/index.js.map +1 -0
  27. package/dist/db/models/funnels.model.d.ts +25 -0
  28. package/dist/db/models/funnels.model.js +39 -0
  29. package/dist/db/models/funnels.model.js.map +1 -0
  30. package/dist/db/models/index.d.ts +7 -0
  31. package/dist/db/models/index.js +24 -0
  32. package/dist/db/models/index.js.map +1 -0
  33. package/dist/db/models/marketing_events.model.d.ts +49 -0
  34. package/dist/db/models/marketing_events.model.js +85 -0
  35. package/dist/db/models/marketing_events.model.js.map +1 -0
  36. package/dist/db/models/marketing_sessions.model.d.ts +33 -0
  37. package/dist/db/models/marketing_sessions.model.js +50 -0
  38. package/dist/db/models/marketing_sessions.model.js.map +1 -0
  39. package/dist/db/models/marketing_settings.model.d.ts +23 -0
  40. package/dist/db/models/marketing_settings.model.js +13 -0
  41. package/dist/db/models/marketing_settings.model.js.map +1 -0
  42. package/dist/db/models/page_snapshots.model.d.ts +27 -0
  43. package/dist/db/models/page_snapshots.model.js +32 -0
  44. package/dist/db/models/page_snapshots.model.js.map +1 -0
  45. package/dist/db/models/retention.d.ts +6 -0
  46. package/dist/db/models/retention.js +26 -0
  47. package/dist/db/models/retention.js.map +1 -0
  48. package/dist/db/models/website_statistics.model.d.ts +31 -0
  49. package/dist/db/models/website_statistics.model.js +63 -0
  50. package/dist/db/models/website_statistics.model.js.map +1 -0
  51. package/dist/db/models/websites.model.d.ts +26 -0
  52. package/dist/db/models/websites.model.js +27 -0
  53. package/dist/db/models/websites.model.js.map +1 -0
  54. package/dist/db/tables/funnels.table.d.ts +31 -0
  55. package/dist/db/tables/funnels.table.js +54 -0
  56. package/dist/db/tables/funnels.table.js.map +1 -0
  57. package/dist/db/tables/index.d.ts +7 -0
  58. package/dist/db/tables/index.js +24 -0
  59. package/dist/db/tables/index.js.map +1 -0
  60. package/dist/db/tables/marketing_events.table.d.ts +15 -0
  61. package/dist/db/tables/marketing_events.table.js +66 -0
  62. package/dist/db/tables/marketing_events.table.js.map +1 -0
  63. package/dist/db/tables/marketing_sessions.table.d.ts +26 -0
  64. package/dist/db/tables/marketing_sessions.table.js +115 -0
  65. package/dist/db/tables/marketing_sessions.table.js.map +1 -0
  66. package/dist/db/tables/marketing_settings.table.d.ts +11 -0
  67. package/dist/db/tables/marketing_settings.table.js +51 -0
  68. package/dist/db/tables/marketing_settings.table.js.map +1 -0
  69. package/dist/db/tables/page_snapshots.table.d.ts +17 -0
  70. package/dist/db/tables/page_snapshots.table.js +72 -0
  71. package/dist/db/tables/page_snapshots.table.js.map +1 -0
  72. package/dist/db/tables/website_statistics.table.d.ts +14 -0
  73. package/dist/db/tables/website_statistics.table.js +60 -0
  74. package/dist/db/tables/website_statistics.table.js.map +1 -0
  75. package/dist/db/tables/websites.table.d.ts +13 -0
  76. package/dist/db/tables/websites.table.js +60 -0
  77. package/dist/db/tables/websites.table.js.map +1 -0
  78. package/dist/hooks/index.d.ts +1 -0
  79. package/dist/hooks/index.js +39 -0
  80. package/dist/hooks/index.js.map +1 -0
  81. package/dist/implementations/dms-marketing/index.d.ts +2 -0
  82. package/dist/implementations/dms-marketing/index.js +8 -0
  83. package/dist/implementations/dms-marketing/index.js.map +1 -0
  84. package/dist/index.d.ts +7 -0
  85. package/dist/index.js +89 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/pages/all.d.ts +5 -0
  88. package/dist/pages/all.js +22 -0
  89. package/dist/pages/all.js.map +1 -0
  90. package/dist/pages/campaigns/page.d.ts +9 -0
  91. package/dist/pages/campaigns/page.js +27 -0
  92. package/dist/pages/campaigns/page.js.map +1 -0
  93. package/dist/pages/funnels/page.d.ts +9 -0
  94. package/dist/pages/funnels/page.js +27 -0
  95. package/dist/pages/funnels/page.js.map +1 -0
  96. package/dist/pages/index.d.ts +4 -0
  97. package/dist/pages/index.js +21 -0
  98. package/dist/pages/index.js.map +1 -0
  99. package/dist/pages/module.d.ts +1 -0
  100. package/dist/pages/module.js +13 -0
  101. package/dist/pages/module.js.map +1 -0
  102. package/dist/pages/overview/page.d.ts +9 -0
  103. package/dist/pages/overview/page.js +27 -0
  104. package/dist/pages/overview/page.js.map +1 -0
  105. package/dist/pages/pages/page.d.ts +9 -0
  106. package/dist/pages/pages/page.js +27 -0
  107. package/dist/pages/pages/page.js.map +1 -0
  108. package/dist/pages/settings/form.d.ts +3 -0
  109. package/dist/pages/settings/form.js +35 -0
  110. package/dist/pages/settings/form.js.map +1 -0
  111. package/dist/pages/settings/page.d.ts +9 -0
  112. package/dist/pages/settings/page.js +27 -0
  113. package/dist/pages/settings/page.js.map +1 -0
  114. package/dist/routes/collect.d.ts +7 -0
  115. package/dist/routes/collect.js +62 -0
  116. package/dist/routes/collect.js.map +1 -0
  117. package/dist/routes/experiments.d.ts +6 -0
  118. package/dist/routes/experiments.js +63 -0
  119. package/dist/routes/experiments.js.map +1 -0
  120. package/dist/routes/funnels.d.ts +16 -0
  121. package/dist/routes/funnels.js +44 -0
  122. package/dist/routes/funnels.js.map +1 -0
  123. package/dist/routes/index.d.ts +8 -0
  124. package/dist/routes/index.js +25 -0
  125. package/dist/routes/index.js.map +1 -0
  126. package/dist/routes/settings.d.ts +8 -0
  127. package/dist/routes/settings.js +50 -0
  128. package/dist/routes/settings.js.map +1 -0
  129. package/dist/routes/snapshot.d.ts +10 -0
  130. package/dist/routes/snapshot.js +147 -0
  131. package/dist/routes/snapshot.js.map +1 -0
  132. package/dist/routes/stats.d.ts +44 -0
  133. package/dist/routes/stats.js +278 -0
  134. package/dist/routes/stats.js.map +1 -0
  135. package/dist/routes/tracker.d.ts +6 -0
  136. package/dist/routes/tracker.js +57 -0
  137. package/dist/routes/tracker.js.map +1 -0
  138. package/dist/routes/websites.d.ts +13 -0
  139. package/dist/routes/websites.js +144 -0
  140. package/dist/routes/websites.js.map +1 -0
  141. package/dist/services/acquisition.d.ts +15 -0
  142. package/dist/services/acquisition.js +153 -0
  143. package/dist/services/acquisition.js.map +1 -0
  144. package/dist/services/bounded-cache.d.ts +14 -0
  145. package/dist/services/bounded-cache.js +45 -0
  146. package/dist/services/bounded-cache.js.map +1 -0
  147. package/dist/services/collect.d.ts +11 -0
  148. package/dist/services/collect.js +193 -0
  149. package/dist/services/collect.js.map +1 -0
  150. package/dist/services/experiment-definitions.d.ts +4 -0
  151. package/dist/services/experiment-definitions.js +36 -0
  152. package/dist/services/experiment-definitions.js.map +1 -0
  153. package/dist/services/experiments/assign.d.ts +5 -0
  154. package/dist/services/experiments/assign.js +52 -0
  155. package/dist/services/experiments/assign.js.map +1 -0
  156. package/dist/services/experiments/index.d.ts +3 -0
  157. package/dist/services/experiments/index.js +20 -0
  158. package/dist/services/experiments/index.js.map +1 -0
  159. package/dist/services/experiments/results.d.ts +20 -0
  160. package/dist/services/experiments/results.js +91 -0
  161. package/dist/services/experiments/results.js.map +1 -0
  162. package/dist/services/experiments/stats.d.ts +12 -0
  163. package/dist/services/experiments/stats.js +62 -0
  164. package/dist/services/experiments/stats.js.map +1 -0
  165. package/dist/services/funnels/compute.d.ts +15 -0
  166. package/dist/services/funnels/compute.js +68 -0
  167. package/dist/services/funnels/compute.js.map +1 -0
  168. package/dist/services/funnels/index.d.ts +2 -0
  169. package/dist/services/funnels/index.js +19 -0
  170. package/dist/services/funnels/index.js.map +1 -0
  171. package/dist/services/funnels/results.d.ts +14 -0
  172. package/dist/services/funnels/results.js +72 -0
  173. package/dist/services/funnels/results.js.map +1 -0
  174. package/dist/services/geoip.d.ts +3 -0
  175. package/dist/services/geoip.js +38 -0
  176. package/dist/services/geoip.js.map +1 -0
  177. package/dist/services/heatmap.d.ts +10 -0
  178. package/dist/services/heatmap.js +180 -0
  179. package/dist/services/heatmap.js.map +1 -0
  180. package/dist/services/index.d.ts +26 -0
  181. package/dist/services/index.js +43 -0
  182. package/dist/services/index.js.map +1 -0
  183. package/dist/services/ingest-guard.d.ts +11 -0
  184. package/dist/services/ingest-guard.js +44 -0
  185. package/dist/services/ingest-guard.js.map +1 -0
  186. package/dist/services/keyed-queue.d.ts +4 -0
  187. package/dist/services/keyed-queue.js +19 -0
  188. package/dist/services/keyed-queue.js.map +1 -0
  189. package/dist/services/origin-guard.d.ts +5 -0
  190. package/dist/services/origin-guard.js +43 -0
  191. package/dist/services/origin-guard.js.map +1 -0
  192. package/dist/services/period.d.ts +2 -0
  193. package/dist/services/period.js +19 -0
  194. package/dist/services/period.js.map +1 -0
  195. package/dist/services/prune.d.ts +7 -0
  196. package/dist/services/prune.js +49 -0
  197. package/dist/services/prune.js.map +1 -0
  198. package/dist/services/query-param.d.ts +1 -0
  199. package/dist/services/query-param.js +11 -0
  200. package/dist/services/query-param.js.map +1 -0
  201. package/dist/services/request-body.d.ts +2 -0
  202. package/dist/services/request-body.js +41 -0
  203. package/dist/services/request-body.js.map +1 -0
  204. package/dist/services/request-meta.d.ts +3 -0
  205. package/dist/services/request-meta.js +19 -0
  206. package/dist/services/request-meta.js.map +1 -0
  207. package/dist/services/rollup-write.d.ts +4 -0
  208. package/dist/services/rollup-write.js +84 -0
  209. package/dist/services/rollup-write.js.map +1 -0
  210. package/dist/services/sessionize.d.ts +23 -0
  211. package/dist/services/sessionize.js +78 -0
  212. package/dist/services/sessionize.js.map +1 -0
  213. package/dist/services/settings.d.ts +6 -0
  214. package/dist/services/settings.js +113 -0
  215. package/dist/services/settings.js.map +1 -0
  216. package/dist/services/snapshots.d.ts +24 -0
  217. package/dist/services/snapshots.js +139 -0
  218. package/dist/services/snapshots.js.map +1 -0
  219. package/dist/services/tenant-funnel.d.ts +3 -0
  220. package/dist/services/tenant-funnel.js +17 -0
  221. package/dist/services/tenant-funnel.js.map +1 -0
  222. package/dist/services/tenant-website.d.ts +5 -0
  223. package/dist/services/tenant-website.js +34 -0
  224. package/dist/services/tenant-website.js.map +1 -0
  225. package/dist/services/url.d.ts +10 -0
  226. package/dist/services/url.js +81 -0
  227. package/dist/services/url.js.map +1 -0
  228. package/dist/services/user-agent.d.ts +2 -0
  229. package/dist/services/user-agent.js +17 -0
  230. package/dist/services/user-agent.js.map +1 -0
  231. package/dist/services/visitor-id.d.ts +1 -0
  232. package/dist/services/visitor-id.js +19 -0
  233. package/dist/services/visitor-id.js.map +1 -0
  234. package/dist/services/website-cache.d.ts +3 -0
  235. package/dist/services/website-cache.js +22 -0
  236. package/dist/services/website-cache.js.map +1 -0
  237. package/dist/types/constants.d.ts +74 -0
  238. package/dist/types/constants.js +79 -0
  239. package/dist/types/constants.js.map +1 -0
  240. package/dist/types/events.d.ts +114 -0
  241. package/dist/types/events.js +29 -0
  242. package/dist/types/events.js.map +1 -0
  243. package/dist/types/index.d.ts +5 -0
  244. package/dist/types/index.js +22 -0
  245. package/dist/types/index.js.map +1 -0
  246. package/dist/types/settings.d.ts +67 -0
  247. package/dist/types/settings.js +58 -0
  248. package/dist/types/settings.js.map +1 -0
  249. package/dist/types/snapshots.d.ts +95 -0
  250. package/dist/types/snapshots.js +41 -0
  251. package/dist/types/snapshots.js.map +1 -0
  252. package/dist/types/statistics.d.ts +38 -0
  253. package/dist/types/statistics.js +33 -0
  254. package/dist/types/statistics.js.map +1 -0
  255. package/dist/utils/experiment-type.d.ts +52 -0
  256. package/dist/utils/experiment-type.js +94 -0
  257. package/dist/utils/experiment-type.js.map +1 -0
  258. package/dist/utils/funnel-steps-type.d.ts +42 -0
  259. package/dist/utils/funnel-steps-type.js +62 -0
  260. package/dist/utils/funnel-steps-type.js.map +1 -0
  261. package/frontend-vue/.editorconfig +12 -0
  262. package/frontend-vue/.prettierrc +7 -0
  263. package/frontend-vue/app/components/CampaignsView.vue +330 -0
  264. package/frontend-vue/app/components/ExperimentInput.vue +128 -0
  265. package/frontend-vue/app/components/FunnelDetail.vue +1026 -0
  266. package/frontend-vue/app/components/FunnelStepsInput.vue +154 -0
  267. package/frontend-vue/app/components/FunnelsView.vue +493 -0
  268. package/frontend-vue/app/components/HeatmapCanvas.vue +116 -0
  269. package/frontend-vue/app/components/NoWebsiteState.vue +18 -0
  270. package/frontend-vue/app/components/OverviewView.vue +493 -0
  271. package/frontend-vue/app/components/PagePreview.vue +915 -0
  272. package/frontend-vue/app/components/PagesView.vue +378 -0
  273. package/frontend-vue/app/components/ScrollDepthOverlay.vue +158 -0
  274. package/frontend-vue/app/components/TextKpiCard.vue +28 -0
  275. package/frontend-vue/app/components/TopListTabsCard.vue +162 -0
  276. package/frontend-vue/app/components/TrackerSnippet.vue +31 -0
  277. package/frontend-vue/app/components/VariationsInput.vue +164 -0
  278. package/frontend-vue/app/composables/useChildId.ts +13 -0
  279. package/frontend-vue/app/composables/useExperiment.ts +59 -0
  280. package/frontend-vue/app/composables/useFunnelSteps.ts +25 -0
  281. package/frontend-vue/app/composables/useLatestRequest.ts +90 -0
  282. package/frontend-vue/app/composables/useMarketingApi.ts +420 -0
  283. package/frontend-vue/app/composables/useMarketingPeriod.ts +66 -0
  284. package/frontend-vue/app/composables/useMarketingRoutes.ts +51 -0
  285. package/frontend-vue/app/composables/useMarketingWebsiteForm.ts +69 -0
  286. package/frontend-vue/app/composables/useMarketingWebsites.ts +80 -0
  287. package/frontend-vue/app/composables/useSnapshotFrame.ts +183 -0
  288. package/frontend-vue/app/plugins/funnel-steps-data-type.client.ts +46 -0
  289. package/frontend-vue/app/utils/dmsComponent.ts +18 -0
  290. package/frontend-vue/app/utils/heatmapPalette.ts +41 -0
  291. package/frontend-vue/app/utils/snapshotViewportUnits.ts +63 -0
  292. package/frontend-vue/dms.frontend.ts +35 -0
  293. package/frontend-vue/eslint.config.mjs +16 -0
  294. package/frontend-vue/i18n/locales/marketing-en-GB.json +382 -0
  295. package/frontend-vue/i18n/locales/marketing-fr-FR.json +382 -0
  296. package/frontend-vue/package.json +30 -0
  297. package/frontend-vue/pnpm-lock.yaml +5226 -0
  298. package/frontend-vue/pnpm-workspace.yaml +2 -0
  299. package/frontend-vue/tests/drafts.test.ts +54 -0
  300. package/frontend-vue/tests/i18n.test.ts +86 -0
  301. package/frontend-vue/tests/period.test.ts +35 -0
  302. package/frontend-vue/tests/registration.test.ts +63 -0
  303. package/frontend-vue/tests/routes.test.ts +31 -0
  304. package/frontend-vue/tests/stubs/frontend-module.ts +56 -0
  305. package/frontend-vue/vitest.config.ts +20 -0
  306. package/package.json +91 -0
  307. package/static/snapshot.js +497 -0
  308. package/static/tracker.js +503 -0
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVisitorHashSecret = getVisitorHashSecret;
4
+ exports.settingsFormValues = settingsFormValues;
5
+ exports.loadSettings = loadSettings;
6
+ exports.applySettingsForm = applySettingsForm;
7
+ const node_crypto_1 = require("node:crypto");
8
+ const config_1 = require("@/config");
9
+ const constants_1 = require("@/types/constants");
10
+ const settings_1 = require("@/types/settings");
11
+ let cachedSecret = "";
12
+ function getVisitorHashSecret() {
13
+ const configured = (0, config_1.getConfig)().visitorHashSecret;
14
+ return configured !== "" ? configured : cachedSecret;
15
+ }
16
+ function generateSecret() {
17
+ return (0, node_crypto_1.randomBytes)(constants_1.VISITOR_SECRET_BYTES).toString("hex");
18
+ }
19
+ function overridesFrom(doc) {
20
+ const overrides = {};
21
+ for (const setting of settings_1.BOOLEAN_SETTINGS) {
22
+ overrides[setting.configKey] = doc[setting.configKey];
23
+ }
24
+ for (const setting of settings_1.NUMBER_SETTINGS) {
25
+ const stored = doc[setting.configKey];
26
+ if (stored != null) {
27
+ overrides[setting.configKey] = stored;
28
+ }
29
+ }
30
+ return overrides;
31
+ }
32
+ function applyDocument(doc) {
33
+ (0, config_1.applyConfigOverrides)(doc ? overridesFrom(doc) : {});
34
+ }
35
+ function defaultDocument() {
36
+ const config = (0, config_1.getConfig)();
37
+ const doc = {};
38
+ for (const setting of settings_1.BOOLEAN_SETTINGS) {
39
+ doc[setting.configKey] = config[setting.configKey];
40
+ }
41
+ for (const setting of settings_1.NUMBER_SETTINGS) {
42
+ doc[setting.configKey] = null;
43
+ }
44
+ return doc;
45
+ }
46
+ function settingsFormValues() {
47
+ const config = (0, config_1.getConfig)();
48
+ const values = {};
49
+ for (const setting of settings_1.BOOLEAN_SETTINGS) {
50
+ values[setting.id] = config[setting.configKey];
51
+ }
52
+ for (const setting of settings_1.NUMBER_SETTINGS) {
53
+ values[setting.id] = Math.max(setting.min, Math.round(config[setting.configKey] / setting.unit));
54
+ }
55
+ return values;
56
+ }
57
+ function buildNextSettings(values, existing) {
58
+ const doc = {};
59
+ const config = (0, config_1.getConfig)();
60
+ for (const setting of settings_1.BOOLEAN_SETTINGS) {
61
+ const submitted = values[setting.id];
62
+ doc[setting.configKey] =
63
+ typeof submitted === "boolean"
64
+ ? submitted
65
+ : (existing?.[setting.configKey] ?? config[setting.configKey]);
66
+ }
67
+ for (const setting of settings_1.NUMBER_SETTINGS) {
68
+ const submitted = values[setting.id];
69
+ doc[setting.configKey] =
70
+ typeof submitted === "number" && !Number.isNaN(submitted)
71
+ ? submitted * setting.unit
72
+ : null;
73
+ }
74
+ return doc;
75
+ }
76
+ async function persistSettings(model, next, existing) {
77
+ const row = existing ?? (await model.getSingleton());
78
+ if (row) {
79
+ Object.assign(row, next);
80
+ await model.update(row);
81
+ return;
82
+ }
83
+ await model.insert({
84
+ ...next,
85
+ visitorHashSecret: cachedSecret || generateSecret(),
86
+ updatedAt: new Date(),
87
+ });
88
+ }
89
+ async function loadSettings(model) {
90
+ let doc = await model.getSingleton();
91
+ if (!doc) {
92
+ doc = {
93
+ ...defaultDocument(),
94
+ visitorHashSecret: generateSecret(),
95
+ updatedAt: new Date(),
96
+ };
97
+ await model.insert(doc);
98
+ }
99
+ else if (!doc.visitorHashSecret) {
100
+ doc.visitorHashSecret = generateSecret();
101
+ await model.update(doc);
102
+ }
103
+ cachedSecret = doc.visitorHashSecret;
104
+ applyDocument(doc);
105
+ }
106
+ async function applySettingsForm(model, values) {
107
+ const existing = await model.getSingleton();
108
+ const next = buildNextSettings(values, existing);
109
+ await persistSettings(model, next, existing);
110
+ applyDocument(next);
111
+ return settingsFormValues();
112
+ }
113
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/services/settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { Website } from "@/db/tables/websites.table";
2
+ import { type SnapshotColorScheme, type SnapshotLayout, type SnapshotRequestInput } from "@/types";
3
+ export declare function snapshotId(websiteId: string, layout: SnapshotLayout, url: string): string;
4
+ export declare function wantsSnapshot(website: Website, url: string, viewportWidth: number): Promise<boolean>;
5
+ export declare function storeSnapshot(website: Website, input: SnapshotRequestInput): Promise<boolean>;
6
+ export interface PageSnapshotPayload {
7
+ layout: SnapshotLayout;
8
+ exact: boolean;
9
+ capturedAt: number;
10
+ origin: string;
11
+ viewport: {
12
+ width: number;
13
+ height: number;
14
+ };
15
+ document: {
16
+ width: number;
17
+ height: number;
18
+ };
19
+ colorScheme?: SnapshotColorScheme;
20
+ bytes: number;
21
+ html: string | null;
22
+ }
23
+ export declare function readPageSnapshot(tenantId: string, websiteId: string, url: string, layout: SnapshotLayout): Promise<PageSnapshotPayload | null>;
24
+ export declare function deleteSnapshots(tenantId: string, websiteId: string, url?: string): Promise<number>;
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.snapshotId = snapshotId;
4
+ exports.wantsSnapshot = wantsSnapshot;
5
+ exports.storeSnapshot = storeSnapshot;
6
+ exports.readPageSnapshot = readPageSnapshot;
7
+ exports.deleteSnapshots = deleteSnapshots;
8
+ const node_crypto_1 = require("node:crypto");
9
+ const node_zlib_1 = require("node:zlib");
10
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
11
+ const db_1 = require("@/db");
12
+ const types_1 = require("@/types");
13
+ const constants_1 = require("@/types/constants");
14
+ const bounded_cache_1 = require("./bounded-cache");
15
+ const url_1 = require("./url");
16
+ const PAGE_PROTOCOLS = ["http:", "https:"];
17
+ const captureTimes = new bounded_cache_1.BoundedCache(constants_1.SNAPSHOT_REFRESH_AGE_MS, constants_1.SNAPSHOT_CACHE_MAX_ENTRIES);
18
+ const promised = new bounded_cache_1.BoundedCache(constants_1.SNAPSHOT_PROMISE_TTL_MS, constants_1.SNAPSHOT_CACHE_MAX_ENTRIES);
19
+ function snapshotId(websiteId, layout, url) {
20
+ return (0, node_crypto_1.createHash)("sha256")
21
+ .update(`${websiteId}\n${layout}\n${url}`)
22
+ .digest("hex");
23
+ }
24
+ async function captureTimeOf(website, id) {
25
+ const cached = captureTimes.get(id);
26
+ if (cached) {
27
+ return cached.value;
28
+ }
29
+ const row = await (0, interface_database_decorators_1.GetModel)(db_1.PageSnapshotsModel, website.tenantId).get(id);
30
+ const time = row?.capturedAt.getTime() ?? 0;
31
+ captureTimes.set(id, time);
32
+ return time;
33
+ }
34
+ async function wantsSnapshot(website, url, viewportWidth) {
35
+ const id = snapshotId(website._id, (0, types_1.layoutOfWidth)(viewportWidth), url);
36
+ const capturedAt = await captureTimeOf(website, id);
37
+ if (Date.now() - capturedAt < constants_1.SNAPSHOT_REFRESH_AGE_MS || promised.get(id)) {
38
+ return false;
39
+ }
40
+ promised.set(id, true);
41
+ return true;
42
+ }
43
+ function pageOrigin(rawUrl) {
44
+ try {
45
+ const url = new URL(rawUrl);
46
+ return PAGE_PROTOCOLS.includes(url.protocol) ? url.origin : undefined;
47
+ }
48
+ catch {
49
+ return undefined;
50
+ }
51
+ }
52
+ async function storeSnapshot(website, input) {
53
+ const origin = pageOrigin(input.url);
54
+ if (!origin) {
55
+ return false;
56
+ }
57
+ const url = (0, url_1.parseTrackedUrl)(input.url).path;
58
+ const layout = (0, types_1.layoutOfWidth)(input.viewport.width);
59
+ const id = snapshotId(website._id, layout, url);
60
+ const model = (0, interface_database_decorators_1.GetModel)(db_1.PageSnapshotsModel, website.tenantId);
61
+ const replacing = (await captureTimeOf(website, id)) > 0;
62
+ if (!replacing &&
63
+ (await model.countByWebsite(website._id)) >= constants_1.MAX_SNAPSHOTS_PER_WEBSITE) {
64
+ return false;
65
+ }
66
+ const stored = "html" in input
67
+ ? {
68
+ document: input.document,
69
+ bytes: Buffer.byteLength(input.html),
70
+ html: (0, node_zlib_1.gzipSync)(input.html).toString("base64"),
71
+ }
72
+ : {
73
+ document: { width: 0, height: 0 },
74
+ bytes: input.oversizeBytes,
75
+ html: "",
76
+ };
77
+ const now = new Date();
78
+ await model.upsert({
79
+ _id: id,
80
+ websiteId: website._id,
81
+ url,
82
+ layout,
83
+ origin,
84
+ viewportWidth: input.viewport.width,
85
+ viewportHeight: input.viewport.height,
86
+ documentWidth: stored.document.width,
87
+ documentHeight: stored.document.height,
88
+ colorScheme: input.colorScheme,
89
+ capturedAt: now,
90
+ bytes: stored.bytes,
91
+ html: stored.html,
92
+ });
93
+ captureTimes.set(id, now.getTime());
94
+ return true;
95
+ }
96
+ function layoutRank(layout) {
97
+ return types_1.SNAPSHOT_LAYOUTS.indexOf(layout);
98
+ }
99
+ function bestFor(wanted) {
100
+ return (a, b) => {
101
+ const backdrop = Number(a.html === "") - Number(b.html === "");
102
+ const distance = Math.abs(layoutRank(a.layout) - layoutRank(wanted)) -
103
+ Math.abs(layoutRank(b.layout) - layoutRank(wanted));
104
+ return backdrop || distance || layoutRank(a.layout) - layoutRank(b.layout);
105
+ };
106
+ }
107
+ async function readPageSnapshot(tenantId, websiteId, url, layout) {
108
+ const rows = await (0, interface_database_decorators_1.GetModel)(db_1.PageSnapshotsModel, tenantId).getByPath(websiteId, url);
109
+ const row = rows.sort(bestFor(layout))[0];
110
+ if (!row) {
111
+ return null;
112
+ }
113
+ return {
114
+ layout: row.layout,
115
+ exact: row.layout === layout,
116
+ capturedAt: row.capturedAt.getTime(),
117
+ origin: row.origin,
118
+ viewport: { width: row.viewportWidth, height: row.viewportHeight },
119
+ document: { width: row.documentWidth, height: row.documentHeight },
120
+ colorScheme: row.colorScheme,
121
+ bytes: row.bytes,
122
+ html: row.html
123
+ ? (0, node_zlib_1.gunzipSync)(Buffer.from(row.html, "base64")).toString("utf8")
124
+ : null,
125
+ };
126
+ }
127
+ async function deleteSnapshots(tenantId, websiteId, url) {
128
+ const deleted = await (0, interface_database_decorators_1.GetModel)(db_1.PageSnapshotsModel, tenantId).deleteByWebsite(websiteId, url);
129
+ if (url) {
130
+ for (const layout of types_1.SNAPSHOT_LAYOUTS) {
131
+ captureTimes.delete(snapshotId(websiteId, layout, url));
132
+ }
133
+ }
134
+ else {
135
+ captureTimes.clear();
136
+ }
137
+ return deleted;
138
+ }
139
+ //# sourceMappingURL=snapshots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshots.js","sourceRoot":"","sources":["../../src/services/snapshots.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type RequestContext } from "@antelopejs/interface-api";
2
+ import type { Funnel } from "@/db/tables/funnels.table";
3
+ export declare function requireTenantFunnel(context: RequestContext, id: string): Promise<Funnel>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireTenantFunnel = requireTenantFunnel;
4
+ const interface_api_1 = require("@antelopejs/interface-api");
5
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
6
+ const request_tenant_1 = require("@antelopejs/interface-dms/request-tenant");
7
+ const db_1 = require("@/db");
8
+ const constants_1 = require("@/types/constants");
9
+ const FUNNEL_NOT_FOUND_MESSAGE = "$page.marketing.errors.funnel_not_found";
10
+ async function requireTenantFunnel(context, id) {
11
+ const funnel = await (0, interface_database_decorators_1.GetModel)(db_1.FunnelsModel, (0, request_tenant_1.getRequestTenantId)(context)).get(id);
12
+ if (!funnel) {
13
+ throw new interface_api_1.HTTPResult(constants_1.HTTP_NOT_FOUND, FUNNEL_NOT_FOUND_MESSAGE);
14
+ }
15
+ return funnel;
16
+ }
17
+ //# sourceMappingURL=tenant-funnel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-funnel.js","sourceRoot":"","sources":["../../src/services/tenant-funnel.ts"],"names":[],"mappings":";;AAeA,kDAWC;AA1BD,6DAA4E;AAC5E,6FAAqE;AACrE,6EAA8E;AAC9E,6BAAoC;AAEpC,iDAAmD;AAEnD,MAAM,wBAAwB,GAAG,yCAAyC,CAAC;AAQpE,KAAK,UAAU,mBAAmB,CACvC,OAAuB,EACvB,EAAU;IAEV,MAAM,MAAM,GAAG,MAAM,IAAA,wCAAQ,EAAC,iBAAY,EAAE,IAAA,mCAAkB,EAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAC1E,EAAE,CACH,CAAC;IACF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,0BAAU,CAAC,0BAAc,EAAE,wBAAwB,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type RequestContext } from "@antelopejs/interface-api";
2
+ import type { Website } from "@/db/tables/websites.table";
3
+ export declare function requireTenantWebsite(context: RequestContext, id: string | undefined): Promise<Website>;
4
+ export declare function purgeWebsiteTrackingData(tenantId: string, websiteId: string): Promise<void>;
5
+ export declare function listTenantWebsites(tenantId: string): Promise<Website[]>;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireTenantWebsite = requireTenantWebsite;
4
+ exports.purgeWebsiteTrackingData = purgeWebsiteTrackingData;
5
+ exports.listTenantWebsites = listTenantWebsites;
6
+ const interface_api_1 = require("@antelopejs/interface-api");
7
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
8
+ const request_tenant_1 = require("@antelopejs/interface-dms/request-tenant");
9
+ const db_1 = require("@/db");
10
+ const constants_1 = require("@/types/constants");
11
+ const snapshots_1 = require("./snapshots");
12
+ const WEBSITE_NOT_FOUND_MESSAGE = "$page.marketing.errors.website_not_found";
13
+ async function requireTenantWebsite(context, id) {
14
+ const website = id ? await (0, interface_database_decorators_1.GetModel)(db_1.WebsitesModel).get(id) : undefined;
15
+ if (!website || website.tenantId !== (0, request_tenant_1.getRequestTenantId)(context)) {
16
+ throw new interface_api_1.HTTPResult(constants_1.HTTP_NOT_FOUND, WEBSITE_NOT_FOUND_MESSAGE);
17
+ }
18
+ return website;
19
+ }
20
+ async function purgeWebsiteTrackingData(tenantId, websiteId) {
21
+ await (0, interface_database_decorators_1.GetModel)(db_1.MarketingEventsModel, tenantId).deleteByWebsite(websiteId);
22
+ await (0, interface_database_decorators_1.GetModel)(db_1.MarketingSessionsModel, tenantId).deleteByWebsite(websiteId);
23
+ await (0, interface_database_decorators_1.GetModel)(db_1.WebsiteStatisticsModel, tenantId).deleteByWebsite(websiteId);
24
+ await (0, snapshots_1.deleteSnapshots)(tenantId, websiteId);
25
+ }
26
+ async function listTenantWebsites(tenantId) {
27
+ const websites = await (0, interface_database_decorators_1.GetModel)(db_1.WebsitesModel).getByTenant(tenantId);
28
+ if (websites.length < 2) {
29
+ return websites;
30
+ }
31
+ const activity = await (0, interface_database_decorators_1.GetModel)(db_1.MarketingSessionsModel, tenantId).getLastActivityByWebsites(websites.map((site) => site._id));
32
+ return [...websites].sort((a, b) => (activity.get(b._id) ?? 0) - (activity.get(a._id) ?? 0));
33
+ }
34
+ //# sourceMappingURL=tenant-website.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-website.js","sourceRoot":"","sources":["../../src/services/tenant-website.ts"],"names":[],"mappings":";;AAqBA,oDASC;AASD,4DAQC;AAMD,gDAaC;AAlED,6DAA4E;AAC5E,6FAAqE;AACrE,6EAA8E;AAC9E,6BAKc;AAEd,iDAAmD;AACnD,2CAA8C;AAE9C,MAAM,yBAAyB,GAAG,0CAA0C,CAAC;AAQtE,KAAK,UAAU,oBAAoB,CACxC,OAAuB,EACvB,EAAsB;IAEtB,MAAM,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,IAAA,wCAAQ,EAAC,kBAAa,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACvE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAA,mCAAkB,EAAC,OAAO,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,0BAAU,CAAC,0BAAc,EAAE,yBAAyB,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AASM,KAAK,UAAU,wBAAwB,CAC5C,QAAgB,EAChB,SAAiB;IAEjB,MAAM,IAAA,wCAAQ,EAAC,yBAAoB,EAAE,QAAQ,CAAC,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IAC1E,MAAM,IAAA,wCAAQ,EAAC,2BAAsB,EAAE,QAAQ,CAAC,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IAC5E,MAAM,IAAA,wCAAQ,EAAC,2BAAsB,EAAE,QAAQ,CAAC,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IAC5E,MAAM,IAAA,2BAAe,EAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAC7C,CAAC;AAMM,KAAK,UAAU,kBAAkB,CAAC,QAAgB;IACvD,MAAM,QAAQ,GAAG,MAAM,IAAA,wCAAQ,EAAC,kBAAa,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACrE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,IAAA,wCAAQ,EAC7B,2BAAsB,EACtB,QAAQ,CACT,CAAC,yBAAyB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAE9D,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CACvB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAClE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { UtmFields } from "@/types";
2
+ export interface ParsedTrackedUrl {
3
+ path: string;
4
+ hostname?: string;
5
+ utm: UtmFields;
6
+ clickIdParam?: string;
7
+ }
8
+ export declare function parseTrackedUrl(rawUrl: string): ParsedTrackedUrl;
9
+ export declare function toBareHostname(value: string | undefined): string | undefined;
10
+ export declare function extractReferrerDomain(referrer: string | undefined, ownHostnames: ReadonlySet<string>): string | undefined;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTrackedUrl = parseTrackedUrl;
4
+ exports.toBareHostname = toBareHostname;
5
+ exports.extractReferrerDomain = extractReferrerDomain;
6
+ const constants_1 = require("@/types/constants");
7
+ const acquisition_1 = require("./acquisition");
8
+ const RELATIVE_URL_BASE = "http://relative.invalid";
9
+ const RELATIVE_HOSTNAME = "relative.invalid";
10
+ const UTM_FIELD_KEYS = [
11
+ "source",
12
+ "medium",
13
+ "campaign",
14
+ "term",
15
+ "content",
16
+ ];
17
+ const UTM_PARAM_PREFIX = "utm_";
18
+ const WWW_PREFIX = "www.";
19
+ function parseTrackedUrl(rawUrl) {
20
+ const url = toUrl(rawUrl);
21
+ if (!url) {
22
+ return { path: rawUrl.slice(0, constants_1.MAX_URL_LENGTH), utm: {} };
23
+ }
24
+ const hostname = url.hostname === RELATIVE_HOSTNAME ? undefined : url.hostname;
25
+ return {
26
+ path: url.pathname.slice(0, constants_1.MAX_URL_LENGTH),
27
+ hostname,
28
+ utm: parseUtm(url),
29
+ clickIdParam: findClickIdParam(url),
30
+ };
31
+ }
32
+ function toUrl(rawUrl) {
33
+ try {
34
+ return new URL(rawUrl, RELATIVE_URL_BASE);
35
+ }
36
+ catch {
37
+ return null;
38
+ }
39
+ }
40
+ function findClickIdParam(url) {
41
+ return acquisition_1.CLICK_ID_PARAMS.find((param) => url.searchParams.get(param));
42
+ }
43
+ function parseUtm(url) {
44
+ const utm = {};
45
+ for (const key of UTM_FIELD_KEYS) {
46
+ const value = url.searchParams.get(`${UTM_PARAM_PREFIX}${key}`);
47
+ if (value) {
48
+ utm[key] = value;
49
+ }
50
+ }
51
+ return utm;
52
+ }
53
+ function toBareHostname(value) {
54
+ if (!value) {
55
+ return undefined;
56
+ }
57
+ const url = toUrl(value);
58
+ const host = url?.hostname && url.hostname !== RELATIVE_HOSTNAME
59
+ ? url.hostname
60
+ : value.split("/")[0].split(":")[0];
61
+ const lower = host.toLowerCase();
62
+ const bare = lower.startsWith(WWW_PREFIX)
63
+ ? lower.slice(WWW_PREFIX.length)
64
+ : lower;
65
+ return bare || undefined;
66
+ }
67
+ function extractReferrerDomain(referrer, ownHostnames) {
68
+ if (!referrer) {
69
+ return undefined;
70
+ }
71
+ const url = toUrl(referrer);
72
+ if (!url || url.hostname === RELATIVE_HOSTNAME) {
73
+ return undefined;
74
+ }
75
+ const domain = toBareHostname(url.hostname);
76
+ if (!domain || ownHostnames.has(domain)) {
77
+ return undefined;
78
+ }
79
+ return domain;
80
+ }
81
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../../src/services/url.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { DeviceInfo } from "@/types";
2
+ export declare function parseDevice(userAgent: string | undefined): DeviceInfo;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseDevice = parseDevice;
4
+ const ua_parser_js_1 = require("ua-parser-js");
5
+ const DEFAULT_DEVICE_TYPE = "desktop";
6
+ function parseDevice(userAgent) {
7
+ if (!userAgent) {
8
+ return {};
9
+ }
10
+ const result = new ua_parser_js_1.UAParser(userAgent).getResult();
11
+ return {
12
+ browser: result.browser.name,
13
+ os: result.os.name,
14
+ deviceType: result.device.type ?? DEFAULT_DEVICE_TYPE,
15
+ };
16
+ }
17
+ //# sourceMappingURL=user-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-agent.js","sourceRoot":"","sources":["../../src/services/user-agent.ts"],"names":[],"mappings":";;AAMA,kCAUC;AAhBD,+CAAwC;AAIxC,MAAM,mBAAmB,GAAG,SAAS,CAAC;AAEtC,SAAgB,WAAW,CAAC,SAA6B;IACvD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,uBAAQ,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,CAAC;IACnD,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;QAC5B,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI;QAClB,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,mBAAmB;KACtD,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function computeVisitorId(secret: string, websiteId: string, ip: string, userAgent: string, now?: Date): string;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.computeVisitorId = computeVisitorId;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const constants_1 = require("@/types/constants");
6
+ const PERIOD_KEY_LENGTH = 7;
7
+ function periodKey(now) {
8
+ return now.toISOString().slice(0, PERIOD_KEY_LENGTH);
9
+ }
10
+ function computeVisitorId(secret, websiteId, ip, userAgent, now = new Date()) {
11
+ const salt = (0, node_crypto_1.createHash)("sha256")
12
+ .update(`${secret}:${periodKey(now)}`)
13
+ .digest("hex");
14
+ return (0, node_crypto_1.createHash)("sha256")
15
+ .update(`${salt}:${websiteId}:${ip}:${userAgent}`)
16
+ .digest("hex")
17
+ .slice(0, constants_1.VISITOR_ID_HEX_LENGTH);
18
+ }
19
+ //# sourceMappingURL=visitor-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visitor-id.js","sourceRoot":"","sources":["../../src/services/visitor-id.ts"],"names":[],"mappings":";;AAiBA,4CAcC;AA/BD,6CAAyC;AACzC,iDAA0D;AAG1D,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAE5B,SAAS,SAAS,CAAC,GAAS;IAC1B,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;AACvD,CAAC;AASD,SAAgB,gBAAgB,CAC9B,MAAc,EACd,SAAiB,EACjB,EAAU,EACV,SAAiB,EACjB,MAAY,IAAI,IAAI,EAAE;IAEtB,MAAM,IAAI,GAAG,IAAA,wBAAU,EAAC,QAAQ,CAAC;SAC9B,MAAM,CAAC,GAAG,MAAM,IAAI,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;SACrC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjB,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,GAAG,IAAI,IAAI,SAAS,IAAI,EAAE,IAAI,SAAS,EAAE,CAAC;SACjD,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,iCAAqB,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Website } from "@/db/tables/websites.table";
2
+ export declare function resolveWebsite(id: string): Promise<Website | undefined>;
3
+ export declare function invalidateWebsiteCache(id: string): void;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveWebsite = resolveWebsite;
4
+ exports.invalidateWebsiteCache = invalidateWebsiteCache;
5
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
6
+ const db_1 = require("@/db");
7
+ const constants_1 = require("@/types/constants");
8
+ const bounded_cache_1 = require("./bounded-cache");
9
+ const websiteCache = new bounded_cache_1.BoundedCache(constants_1.WEBSITE_CACHE_TTL_MS);
10
+ async function resolveWebsite(id) {
11
+ const hit = websiteCache.get(id);
12
+ if (hit) {
13
+ return hit.value;
14
+ }
15
+ const website = await (0, interface_database_decorators_1.GetModel)(db_1.WebsitesModel).get(id);
16
+ websiteCache.set(id, website);
17
+ return website;
18
+ }
19
+ function invalidateWebsiteCache(id) {
20
+ websiteCache.delete(id);
21
+ }
22
+ //# sourceMappingURL=website-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"website-cache.js","sourceRoot":"","sources":["../../src/services/website-cache.ts"],"names":[],"mappings":";;AAaA,wCAQC;AAMD,wDAEC;AA7BD,6FAAqE;AACrE,6BAAqC;AAErC,iDAAyD;AACzD,mDAA+C;AAK/C,MAAM,YAAY,GAAG,IAAI,4BAAY,CACnC,gCAAoB,CACrB,CAAC;AAEK,KAAK,UAAU,cAAc,CAAC,EAAU;IAC7C,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjC,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,GAAG,CAAC,KAAK,CAAC;IACnB,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,IAAA,wCAAQ,EAAC,kBAAa,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACtD,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,OAAO,CAAC;AACjB,CAAC;AAMD,SAAgB,sBAAsB,CAAC,EAAU;IAC/C,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,74 @@
1
+ export declare const MARKETING_MODULE_ID = "marketing";
2
+ export declare const OVERVIEW_PAGE_ID = "overview";
3
+ export declare const FRONTEND_MODULE_NAME = "@antelopejs/dms-marketing-frontend-vue";
4
+ export declare const MS_PER_SECOND = 1000;
5
+ export declare const MS_PER_MINUTE: number;
6
+ export declare const MS_PER_HOUR: number;
7
+ export declare const MS_PER_DAY: number;
8
+ export declare const DAYS_PER_MONTH = 30;
9
+ export declare const DAYS_PER_YEAR = 365;
10
+ export declare const MAX_QUERY_PERIOD_DAYS = 90;
11
+ export declare const DEFAULT_QUERY_PERIOD_DAYS = 7;
12
+ export declare const DEFAULT_SESSION_IDLE_TIMEOUT_MS: number;
13
+ export declare const DEFAULT_RAW_EVENTS_RETENTION_MS: number;
14
+ export declare const DEFAULT_STATISTICS_RETENTION_MS: number;
15
+ export declare const MAX_STATISTICS_RETENTION_DAYS = 760;
16
+ export declare const DEFAULT_HEATMAP_SAMPLE_RATIO = 0.1;
17
+ export declare const MAX_COLLECT_BATCH_SIZE = 25;
18
+ export declare const MAX_TRUSTED_CLIENT_CLOCK_SKEW_MS: number;
19
+ export declare const MAX_URL_LENGTH = 500;
20
+ export declare const MAX_TITLE_LENGTH = 200;
21
+ export declare const MAX_EVENT_NAME_LENGTH = 50;
22
+ export declare const MAX_EVENT_DATA_BYTES = 4096;
23
+ export declare const MAX_WEBSITE_ID_LENGTH = 64;
24
+ export declare const MAX_NAME_LENGTH = 100;
25
+ export declare const MAX_DOMAIN_LENGTH = 253;
26
+ export declare const MAX_EXTRA_DOMAINS = 20;
27
+ export declare const MAX_SCREEN_AND_LANGUAGE_CHARS = 16;
28
+ export declare const MIN_FUNNEL_STEPS = 1;
29
+ export declare const MAX_FUNNEL_STEPS = 10;
30
+ export declare const MAX_FUNNEL_STEP_VALUE_LENGTH = 500;
31
+ export declare const MAX_CONVERSION_WINDOW_HOURS = 720;
32
+ export declare const DEFAULT_CONVERSION_WINDOW_HOURS = 24;
33
+ export declare const MIN_EXPERIMENT_VARIATIONS = 2;
34
+ export declare const MAX_EXPERIMENT_VARIATIONS = 8;
35
+ export declare const MAX_EXPERIMENT_KEY_LENGTH = 64;
36
+ export declare const ASSIGNMENT_HASH_HEX_CHARS = 8;
37
+ export declare const EXPERIMENT_SIGNIFICANCE_LEVEL = 0.05;
38
+ export declare const EXPERIMENT_SRM_P_THRESHOLD = 0.001;
39
+ export declare const MIN_OUTCOMES_PER_CELL = 5;
40
+ export declare const MAX_ENTRIES_PER_TOP_MAP = 50;
41
+ export declare const CAMPAIGN_KEY_SEPARATOR = "\u001F";
42
+ export declare const TOP_MAPS_RETENTION_DAYS = 90;
43
+ export declare const DEFAULT_PAGES_LIST_LIMIT = 100;
44
+ export declare const MAX_PAGES_LIST_LIMIT = 200;
45
+ export declare const MAX_FUNNEL_EVENTS = 200000;
46
+ export declare const MAX_HEATMAP_EVENTS = 50000;
47
+ export declare const HEATMAP_DIVISIONS_PER_AXIS = 50;
48
+ export declare const SCROLL_DEPTH_SCALE = 100;
49
+ export declare const MAX_ANCHORED_HEATMAP_CELLS = 2000;
50
+ export declare const MAX_SNAPSHOT_BYTES: number;
51
+ export declare const MAX_SNAPSHOTS_PER_WEBSITE = 1000;
52
+ export declare const MAX_REPORTED_SNAPSHOT_BYTES: number;
53
+ export declare const MAX_SNAPSHOT_VIEWPORT_PX = 10000;
54
+ export declare const MAX_SNAPSHOT_DOCUMENT_PX = 200000;
55
+ export declare const DEFAULT_SNAPSHOT_RETENTION_MS: number;
56
+ export declare const SNAPSHOT_REFRESH_AGE_MS: number;
57
+ export declare const SNAPSHOT_PROMISE_TTL_MS: number;
58
+ export declare const SNAPSHOT_CACHE_MAX_ENTRIES = 10000;
59
+ export declare const VISITOR_ID_HEX_LENGTH = 32;
60
+ export declare const VISITOR_SECRET_BYTES = 32;
61
+ export declare const SESSION_CACHE_MAX_ENTRIES = 10000;
62
+ export declare const MAX_CACHE_ENTRIES = 1000;
63
+ export declare const WEBSITE_CACHE_TTL_MS = 30000;
64
+ export declare const EXPERIMENT_DEFINITIONS_CACHE_TTL_MS = 30000;
65
+ export declare const COLLECT_RATE_LIMIT_WINDOW_MS: number;
66
+ export declare const MAX_EVENTS_PER_WINDOW_PER_SOURCE = 600;
67
+ export declare const RATE_LIMIT_MAX_SOURCES = 50000;
68
+ export declare const MAX_SNAPSHOTS_PER_WINDOW_PER_SOURCE = 3;
69
+ export declare const TRACKER_CACHE_MAX_AGE_SECONDS = 3600;
70
+ export declare const API_BASE_PATH = "/api/marketing";
71
+ export declare const HTTP_BAD_REQUEST = 400;
72
+ export declare const HTTP_FORBIDDEN = 403;
73
+ export declare const HTTP_NOT_FOUND = 404;
74
+ export declare const HTTP_PAYLOAD_TOO_LARGE = 413;