@huloglobal/vendure-plugin-visitor-analytics 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +83 -15
  2. package/dist/abandoned-cart.controller.d.ts +78 -0
  3. package/dist/abandoned-cart.controller.d.ts.map +1 -0
  4. package/dist/abandoned-cart.controller.js +251 -0
  5. package/dist/abandoned-cart.controller.js.map +1 -0
  6. package/dist/abandoned-cart.entity.d.ts +61 -0
  7. package/dist/abandoned-cart.entity.d.ts.map +1 -0
  8. package/dist/abandoned-cart.entity.js +143 -0
  9. package/dist/abandoned-cart.entity.js.map +1 -0
  10. package/dist/abandoned-cart.scanner.d.ts +34 -0
  11. package/dist/abandoned-cart.scanner.d.ts.map +1 -0
  12. package/dist/abandoned-cart.scanner.js +85 -0
  13. package/dist/abandoned-cart.scanner.js.map +1 -0
  14. package/dist/abandoned-cart.service.d.ts +92 -0
  15. package/dist/abandoned-cart.service.d.ts.map +1 -0
  16. package/dist/abandoned-cart.service.js +276 -0
  17. package/dist/abandoned-cart.service.js.map +1 -0
  18. package/dist/index.d.ts +6 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +13 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/journey-buffs.controller.d.ts +43 -0
  23. package/dist/journey-buffs.controller.d.ts.map +1 -0
  24. package/dist/journey-buffs.controller.js +79 -0
  25. package/dist/journey-buffs.controller.js.map +1 -0
  26. package/dist/journey-buffs.service.d.ts +53 -0
  27. package/dist/journey-buffs.service.d.ts.map +1 -0
  28. package/dist/journey-buffs.service.js +141 -0
  29. package/dist/journey-buffs.service.js.map +1 -0
  30. package/dist/plugin.d.ts +5 -0
  31. package/dist/plugin.d.ts.map +1 -1
  32. package/dist/plugin.js +35 -3
  33. package/dist/plugin.js.map +1 -1
  34. package/dist/product-co-view.entity.d.ts +19 -0
  35. package/dist/product-co-view.entity.d.ts.map +1 -0
  36. package/dist/product-co-view.entity.js +52 -0
  37. package/dist/product-co-view.entity.js.map +1 -0
  38. package/dist/recommendations.controller.d.ts +72 -0
  39. package/dist/recommendations.controller.d.ts.map +1 -0
  40. package/dist/recommendations.controller.js +123 -0
  41. package/dist/recommendations.controller.js.map +1 -0
  42. package/dist/recommendations.service.d.ts +62 -0
  43. package/dist/recommendations.service.d.ts.map +1 -0
  44. package/dist/recommendations.service.js +167 -0
  45. package/dist/recommendations.service.js.map +1 -0
  46. package/dist/search-analytics.controller.d.ts +36 -0
  47. package/dist/search-analytics.controller.d.ts.map +1 -0
  48. package/dist/search-analytics.controller.js +86 -0
  49. package/dist/search-analytics.controller.js.map +1 -0
  50. package/dist/search-analytics.service.d.ts +36 -0
  51. package/dist/search-analytics.service.d.ts.map +1 -0
  52. package/dist/search-analytics.service.js +105 -0
  53. package/dist/search-analytics.service.js.map +1 -0
  54. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -2,46 +2,100 @@
2
2
 
3
3
  All notable changes to `@huloglobal/vendure-plugin-visitor-analytics` are
4
4
  documented here. The format follows
5
- [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this
6
- project adheres to [semantic versioning](https://semver.org/spec/v2.0.0.html).
5
+ [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project
6
+ adheres to [semantic versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [0.4.1]
8
+ ## [0.7.0] — 2026-07-04
9
+
10
+ ### Added
11
+ - Boot-time compatibility check via the new SDK helper
12
+ `warnIfIncompatibleVendure()`. Logs a non-fatal warning when the runtime
13
+ `@vendure/core` version is outside the tested range. Silent when inside;
14
+ fail-open on unparseable versions.
15
+
16
+ ### Changed
17
+ - Peer dep on `@vendure/core` tightened to `>=3.5.0 <4.0.0` — Vendure 3.5,
18
+ 3.6 and 3.7 are all covered. Anything under 3.5 has never been tested;
19
+ anything from 4.0 upwards is deferred until the changelog is reviewed.
20
+ - Uses `@huloglobal/vendure-licence-sdk@^0.6.0`.
21
+
22
+ ## [0.6.0] — 2026-06-23
23
+
24
+ ### Added
25
+ - Vendure Admin API GraphQL extensions. Operator endpoints are now
26
+ first-class GraphQL queries alongside the existing REST admin
27
+ endpoints: `huloVisitorSummary`, `huloVisitorSources`,
28
+ `huloVisitorTopPages`, `huloVisitorFunnel`, `huloVisitorJourney`.
29
+ - Storefront path (`POST /ees/track`) stays REST — it's anonymous,
30
+ high-frequency, and can ingest millions of events a day; the
31
+ resolver stack would add pointless overhead per event.
32
+
33
+ ## [0.5.0] — 2026-06-23
34
+
35
+ ### Added
36
+ - Tier-gating on every premium feature via the SDK's `isLicensed()`
37
+ helper. Unlicensed installs get:
38
+ - a hard 100 events / UTC day cap on `POST /ees/track` (returns
39
+ `{skipped: 'free-tier-cap'}` after that);
40
+ - live SSE feed 402;
41
+ - conversion-goal creation 402;
42
+ - CSV export 402.
43
+ - Anti-tamper heartbeat via the SDK.
44
+
45
+ ### Changed
46
+ - Relicensed the GitHub source to AGPL-3.0. Published npm builds remain
47
+ under the commercial licence documented at
48
+ <https://huloglobal.com/legal/terms/>.
49
+ - npm builds now include Sigstore provenance attestations.
50
+
51
+ ## [0.4.3] — 2026-06-21
52
+
53
+ ### Fixed
54
+ - Dropped the conflicting `display: block` on mobile tables that broke
55
+ the row / cell alignment.
56
+
57
+ ## [0.4.2] — 2026-06-21
58
+
59
+ ### Changed
60
+ - 44px minimum tap targets on every interactive element in the admin UI.
61
+
62
+ ## [0.4.1] — 2026-06-21
9
63
 
10
64
  ### Changed
11
65
  - Comprehensive README refresh — documents the full v0.4 feature set
12
66
  with the storefront snippet, every privacy + security option, and
13
67
  the conversion-goals API.
14
68
 
15
- ## [0.4.0]
69
+ ## [0.4.0] — 2026-06-20
16
70
 
17
71
  ### Added
18
72
  - Signed visitor + session cookies via the licence-sdk `signValue` /
19
73
  `verifySignedValue` helpers — tampered cookies are rejected.
20
74
  - `Secure` cookie flag is set automatically when serving over HTTPS.
21
- - Rate limiter (240/60s default) on `POST /ees/track`.
75
+ - Rate limiter (240 requests / 60s default) on `POST /ees/track`.
22
76
  - `corsAllowedOrigins` option restricts CORS reflection to the
23
77
  configured list (legacy wildcard preserved when empty).
24
78
  - Security headers on every response.
25
79
  - Opt-in retention sweeper via `options.retention`.
26
80
 
27
- ## [0.3.3]
81
+ ## [0.3.3] — 2026-06-20
28
82
 
29
83
  ### Changed
30
- - Mobile-friendly admin UI — summary cards reflow, tables scroll
31
- inside their card, profile drawer goes full-width.
84
+ - Mobile-friendly admin UI — summary cards reflow, tables scroll inside
85
+ their card, profile drawer goes full-width.
32
86
 
33
- ## [0.3.2]
87
+ ## [0.3.2] — 2026-06-20
34
88
 
35
89
  ### Changed
36
90
  - Republish targeting `@huloglobal/vendure-licence-sdk@^0.2.0`.
37
91
 
38
- ## [0.3.1]
92
+ ## [0.3.1] — 2026-06-20
39
93
 
40
94
  ### Added
41
95
  - `UpdateChecker` integration — `/ees/visitors/status` endpoint returns
42
96
  version + update info; admin banner appears on new releases.
43
97
 
44
- ## [0.3.0]
98
+ ## [0.3.0] — 2026-06-20
45
99
 
46
100
  ### Added
47
101
  - **Conversion goals** — new `ConversionGoal` entity with a URL-glob
@@ -62,7 +116,7 @@ project adheres to [semantic versioning](https://semver.org/spec/v2.0.0.html).
62
116
  `consent:true` or cookie `ees_consent=1`
63
117
  - **CSV export** — `GET /ees/visitors/export.csv?days=N` (max 90).
64
118
 
65
- ## [0.2.0]
119
+ ## [0.2.0] — 2026-06-19
66
120
 
67
121
  ### Added
68
122
  - **UTM attribution** — `utmSource` / `utmMedium` / `utmCampaign` /
@@ -78,7 +132,7 @@ project adheres to [semantic versioning](https://semver.org/spec/v2.0.0.html).
78
132
  - **Custom event recipes** — README section with copy-paste storefront
79
133
  snippets for add-to-cart, search, quote-request, newsletter signup.
80
134
 
81
- ## [0.1.0] — Unreleased
135
+ ## [0.1.0] — 2026-06-19
82
136
 
83
137
  ### Added
84
138
  - `VisitorAnalyticsPlugin` — ingest endpoint + admin dashboards.
@@ -92,5 +146,19 @@ project adheres to [semantic versioning](https://semver.org/spec/v2.0.0.html).
92
146
  profile + journey.
93
147
  - Admin UI: summary tiles, funnel bars, top + exit page tables,
94
148
  recent visitors table with clickable profile drawer.
95
- - Licence verification via `@huloglobal/vendure-licence-sdk` with revocation
96
- polling.
149
+ - Licence verification via `@huloglobal/vendure-licence-sdk` with
150
+ revocation polling.
151
+
152
+ [0.7.0]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.7.0
153
+ [0.6.0]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.6.0
154
+ [0.5.0]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.5.0
155
+ [0.4.3]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.4.3
156
+ [0.4.2]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.4.2
157
+ [0.4.1]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.4.1
158
+ [0.4.0]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.4.0
159
+ [0.3.3]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.3.3
160
+ [0.3.2]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.3.2
161
+ [0.3.1]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.3.1
162
+ [0.3.0]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.3.0
163
+ [0.2.0]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.2.0
164
+ [0.1.0]: https://github.com/exceeded/vendure-plugin-visitor-analytics/releases/tag/v0.1.0
@@ -0,0 +1,78 @@
1
+ import { RequestContext } from '@vendure/core';
2
+ import { Request, Response } from 'express';
3
+ import { AbandonedCartService } from './abandoned-cart.service';
4
+ /**
5
+ * Admin API for the Abandoned Cart feature.
6
+ *
7
+ * Endpoints:
8
+ * GET /ees/abandoned-carts — paginated list with filters
9
+ * GET /ees/abandoned-carts/summary — totals + top-value + recovery rate
10
+ * GET /ees/abandoned-carts/:id — detail incl. parsed items
11
+ * POST /ees/abandoned-carts/:id/recovery-link — mint/reissue signed URL
12
+ * POST /ees/abandoned-carts/:id/status — mark recovered/dismissed
13
+ * GET /ees/abandoned-carts/export.csv — CSV export
14
+ *
15
+ * Storefront-side (unauthenticated):
16
+ * GET /ees/recover-cart?t=... — resolve a token → items
17
+ */
18
+ export declare class AbandonedCartController {
19
+ private readonly service;
20
+ constructor(service: AbandonedCartService);
21
+ list(ctx: RequestContext, takeRaw?: string, skipRaw?: string, status?: string, minValueRaw?: string, email?: string): Promise<{
22
+ items: any;
23
+ total: number;
24
+ take: number;
25
+ skip: number;
26
+ }>;
27
+ summary(ctx: RequestContext, daysRaw?: string): Promise<{
28
+ windowDays: number;
29
+ total: number;
30
+ openCount: number;
31
+ recoveredCount: number;
32
+ convertedCount: number;
33
+ expiredCount: number;
34
+ dismissedCount: number;
35
+ recoveryRatePct: number;
36
+ totalValueMinor: number;
37
+ recoveredValueMinor: number;
38
+ avgValueMinor: number;
39
+ }>;
40
+ exportCsv(ctx: RequestContext, res: Response, daysRaw?: string): Promise<void>;
41
+ detail(ctx: RequestContext, idRaw: string): Promise<any>;
42
+ issueRecoveryLink(ctx: RequestContext, idRaw: string): Promise<{
43
+ error: string;
44
+ hint: string;
45
+ ok?: undefined;
46
+ url?: undefined;
47
+ } | {
48
+ ok: boolean;
49
+ url: string;
50
+ error?: undefined;
51
+ hint?: undefined;
52
+ }>;
53
+ setStatus(ctx: RequestContext, idRaw: string, body: {
54
+ status?: string;
55
+ }): Promise<{
56
+ error: string;
57
+ ok?: undefined;
58
+ } | {
59
+ ok: boolean;
60
+ error?: undefined;
61
+ }>;
62
+ /**
63
+ * Public storefront endpoint — decodes a recovery token into a set
64
+ * of cart items the storefront can restore. Rate-limited by the
65
+ * plugin's usual ingest limiter (same origin as the tracker).
66
+ */
67
+ recover(req: Request, token?: string): Promise<{
68
+ error: string;
69
+ } | {
70
+ id: number;
71
+ currency: string;
72
+ items: any[];
73
+ email: string | null;
74
+ ok: boolean;
75
+ error?: undefined;
76
+ }>;
77
+ }
78
+ //# sourceMappingURL=abandoned-cart.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abandoned-cart.controller.d.ts","sourceRoot":"","sources":["../src/abandoned-cart.controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,cAAc,EAAqB,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE;;;;;;;;;;;;;GAaG;AACH,qBACa,uBAAuB;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,oBAAoB;IAIpD,IAAI,CACC,GAAG,EAAE,cAAc,EACX,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,EACvB,KAAK,CAAC,EAAE,MAAM;;;;;;IAuC5B,OAAO,CAAQ,GAAG,EAAE,cAAc,EAAiB,OAAO,CAAC,EAAE,MAAM;;;;;;;;;;;;;IAuCnE,SAAS,CAAQ,GAAG,EAAE,cAAc,EAAS,GAAG,EAAE,QAAQ,EAAiB,OAAO,CAAC,EAAE,MAAM;IA+B3F,MAAM,CAAQ,GAAG,EAAE,cAAc,EAAe,KAAK,EAAE,MAAM;IAgB7D,iBAAiB,CAAQ,GAAG,EAAE,cAAc,EAAe,KAAK,EAAE,MAAM;;;;;;;;;;;IASxE,SAAS,CACJ,GAAG,EAAE,cAAc,EACb,KAAK,EAAE,MAAM,EAClB,IAAI,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;IAWrC;;;;OAIG;IAEG,OAAO,CAAQ,GAAG,EAAE,OAAO,EAAc,KAAK,CAAC,EAAE,MAAM;;;;;;;;;;CAOhE"}
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.AbandonedCartController = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const core_1 = require("@vendure/core");
18
+ const abandoned_cart_service_1 = require("./abandoned-cart.service");
19
+ /**
20
+ * Admin API for the Abandoned Cart feature.
21
+ *
22
+ * Endpoints:
23
+ * GET /ees/abandoned-carts — paginated list with filters
24
+ * GET /ees/abandoned-carts/summary — totals + top-value + recovery rate
25
+ * GET /ees/abandoned-carts/:id — detail incl. parsed items
26
+ * POST /ees/abandoned-carts/:id/recovery-link — mint/reissue signed URL
27
+ * POST /ees/abandoned-carts/:id/status — mark recovered/dismissed
28
+ * GET /ees/abandoned-carts/export.csv — CSV export
29
+ *
30
+ * Storefront-side (unauthenticated):
31
+ * GET /ees/recover-cart?t=... — resolve a token → items
32
+ */
33
+ let AbandonedCartController = class AbandonedCartController {
34
+ constructor(service) {
35
+ this.service = service;
36
+ }
37
+ async list(ctx, takeRaw, skipRaw, status, minValueRaw, email) {
38
+ var _a;
39
+ const take = Math.min(Math.max(1, parseInt(takeRaw || '25', 10) || 25), 200);
40
+ const skip = Math.max(0, parseInt(skipRaw || '0', 10) || 0);
41
+ const where = [];
42
+ const params = [];
43
+ if (status) {
44
+ where.push('status = ?');
45
+ params.push(status);
46
+ }
47
+ if (minValueRaw) {
48
+ const v = parseInt(minValueRaw, 10);
49
+ if (Number.isFinite(v)) {
50
+ where.push('totalMinor >= ?');
51
+ params.push(v);
52
+ }
53
+ }
54
+ if (email) {
55
+ where.push('LOWER(email) LIKE ?');
56
+ params.push(`%${email.toLowerCase()}%`);
57
+ }
58
+ const clause = where.length ? `WHERE ${where.join(' AND ')}` : '';
59
+ const conn = this.service.connection.rawConnection;
60
+ const [rows, totalRow] = await Promise.all([
61
+ conn.query(`SELECT id, sessionId, visitorId, customerId, currency, totalMinor, itemCount,
62
+ email, status, abandonedAt, recoveredAt, notificationSent,
63
+ utmSource, utmMedium, countryCode
64
+ FROM abandoned_cart
65
+ ${clause}
66
+ ORDER BY abandonedAt DESC
67
+ LIMIT ? OFFSET ?`, [...params, take, skip]),
68
+ conn.query(`SELECT COUNT(*) AS c FROM abandoned_cart ${clause}`, params),
69
+ ]);
70
+ return {
71
+ items: rows,
72
+ total: Number(((_a = totalRow === null || totalRow === void 0 ? void 0 : totalRow[0]) === null || _a === void 0 ? void 0 : _a.c) || 0),
73
+ take, skip,
74
+ };
75
+ }
76
+ async summary(ctx, daysRaw) {
77
+ const days = Math.min(Math.max(1, parseInt(daysRaw || '30', 10) || 30), 365);
78
+ const since = new Date(Date.now() - days * 86400000);
79
+ const conn = this.service.connection.rawConnection;
80
+ const rows = await conn.query(`SELECT
81
+ COUNT(*) AS total,
82
+ SUM(status = 'abandoned') AS openCount,
83
+ SUM(status = 'recovered') AS recoveredCount,
84
+ SUM(status = 'converted') AS convertedCount,
85
+ SUM(status = 'expired') AS expiredCount,
86
+ SUM(status = 'dismissed') AS dismissedCount,
87
+ SUM(totalMinor) AS totalValueMinor,
88
+ SUM(CASE WHEN status IN ('recovered','converted') THEN totalMinor ELSE 0 END) AS recoveredValueMinor,
89
+ AVG(totalMinor) AS avgValueMinor
90
+ FROM abandoned_cart
91
+ WHERE abandonedAt >= ?`, [since]);
92
+ const s = (rows === null || rows === void 0 ? void 0 : rows[0]) || {};
93
+ const total = Number(s.total || 0);
94
+ const rec = Number(s.recoveredCount || 0) + Number(s.convertedCount || 0);
95
+ return {
96
+ windowDays: days,
97
+ total,
98
+ openCount: Number(s.openCount || 0),
99
+ recoveredCount: Number(s.recoveredCount || 0),
100
+ convertedCount: Number(s.convertedCount || 0),
101
+ expiredCount: Number(s.expiredCount || 0),
102
+ dismissedCount: Number(s.dismissedCount || 0),
103
+ recoveryRatePct: total ? Math.round((rec / total) * 1000) / 10 : 0,
104
+ totalValueMinor: Number(s.totalValueMinor || 0),
105
+ recoveredValueMinor: Number(s.recoveredValueMinor || 0),
106
+ avgValueMinor: Math.round(Number(s.avgValueMinor || 0)),
107
+ };
108
+ }
109
+ async exportCsv(ctx, res, daysRaw) {
110
+ const days = Math.min(Math.max(1, parseInt(daysRaw || '30', 10) || 30), 365);
111
+ const since = new Date(Date.now() - days * 86400000);
112
+ const conn = this.service.connection.rawConnection;
113
+ const rows = await conn.query(`SELECT id, sessionId, visitorId, customerId, currency, totalMinor, itemCount,
114
+ email, status, abandonedAt, recoveredAt, utmSource, utmMedium, utmCampaign, countryCode
115
+ FROM abandoned_cart
116
+ WHERE abandonedAt >= ?
117
+ ORDER BY abandonedAt DESC
118
+ LIMIT 50000`, [since]);
119
+ res.setHeader('content-type', 'text/csv; charset=utf-8');
120
+ res.setHeader('content-disposition', `attachment; filename="abandoned-carts-${new Date().toISOString().slice(0, 10)}.csv"`);
121
+ const esc = (v) => {
122
+ const s = v == null ? '' : String(v);
123
+ return /[,"\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
124
+ };
125
+ const cols = ['id', 'sessionId', 'visitorId', 'customerId', 'currency', 'totalMinor', 'itemCount',
126
+ 'email', 'status', 'abandonedAt', 'recoveredAt', 'utmSource', 'utmMedium', 'utmCampaign', 'countryCode'];
127
+ res.write(cols.join(',') + '\n');
128
+ for (const r of rows) {
129
+ res.write(cols.map(c => esc(r[c])).join(',') + '\n');
130
+ }
131
+ res.end();
132
+ }
133
+ async detail(ctx, idRaw) {
134
+ const id = parseInt(idRaw, 10);
135
+ const conn = this.service.connection.rawConnection;
136
+ const rows = await conn.query(`SELECT * FROM abandoned_cart WHERE id = ? LIMIT 1`, [id]);
137
+ if (!(rows === null || rows === void 0 ? void 0 : rows.length))
138
+ return { error: 'not-found' };
139
+ const r = rows[0];
140
+ let items = [];
141
+ try {
142
+ items = JSON.parse(r.itemsJson || '[]');
143
+ }
144
+ catch { }
145
+ return { ...r, items };
146
+ }
147
+ async issueRecoveryLink(ctx, idRaw) {
148
+ const id = parseInt(idRaw, 10);
149
+ const url = await this.service.issueRecoveryLink(id);
150
+ if (!url)
151
+ return { error: 'recovery-disabled-or-not-found', hint: 'Set abandonment.recoveryLinkSecret in plugin options' };
152
+ return { ok: true, url };
153
+ }
154
+ async setStatus(ctx, idRaw, body) {
155
+ const id = parseInt(idRaw, 10);
156
+ const status = String((body === null || body === void 0 ? void 0 : body.status) || '');
157
+ if (!['recovered', 'dismissed', 'abandoned'].includes(status)) {
158
+ return { error: 'invalid-status' };
159
+ }
160
+ const ok = await this.service.markStatus(id, status);
161
+ return ok ? { ok: true } : { error: 'not-found' };
162
+ }
163
+ /**
164
+ * Public storefront endpoint — decodes a recovery token into a set
165
+ * of cart items the storefront can restore. Rate-limited by the
166
+ * plugin's usual ingest limiter (same origin as the tracker).
167
+ */
168
+ async recover(req, token) {
169
+ const t = String(token || '').trim();
170
+ if (!t)
171
+ return { error: 'missing-token' };
172
+ const result = await this.service.findByRecoveryToken(t);
173
+ if (!result)
174
+ return { error: 'expired-or-invalid' };
175
+ return { ok: true, ...result };
176
+ }
177
+ };
178
+ exports.AbandonedCartController = AbandonedCartController;
179
+ __decorate([
180
+ (0, common_1.Get)('abandoned-carts'),
181
+ (0, core_1.Allow)(core_1.Permission.ReadCustomer),
182
+ __param(0, (0, core_1.Ctx)()),
183
+ __param(1, (0, common_1.Query)('take')),
184
+ __param(2, (0, common_1.Query)('skip')),
185
+ __param(3, (0, common_1.Query)('status')),
186
+ __param(4, (0, common_1.Query)('minValue')),
187
+ __param(5, (0, common_1.Query)('email')),
188
+ __metadata("design:type", Function),
189
+ __metadata("design:paramtypes", [core_1.RequestContext, String, String, String, String, String]),
190
+ __metadata("design:returntype", Promise)
191
+ ], AbandonedCartController.prototype, "list", null);
192
+ __decorate([
193
+ (0, common_1.Get)('abandoned-carts/summary'),
194
+ (0, core_1.Allow)(core_1.Permission.ReadCustomer),
195
+ __param(0, (0, core_1.Ctx)()),
196
+ __param(1, (0, common_1.Query)('days')),
197
+ __metadata("design:type", Function),
198
+ __metadata("design:paramtypes", [core_1.RequestContext, String]),
199
+ __metadata("design:returntype", Promise)
200
+ ], AbandonedCartController.prototype, "summary", null);
201
+ __decorate([
202
+ (0, common_1.Get)('abandoned-carts/export.csv'),
203
+ (0, core_1.Allow)(core_1.Permission.ReadCustomer),
204
+ __param(0, (0, core_1.Ctx)()),
205
+ __param(1, (0, common_1.Res)()),
206
+ __param(2, (0, common_1.Query)('days')),
207
+ __metadata("design:type", Function),
208
+ __metadata("design:paramtypes", [core_1.RequestContext, Object, String]),
209
+ __metadata("design:returntype", Promise)
210
+ ], AbandonedCartController.prototype, "exportCsv", null);
211
+ __decorate([
212
+ (0, common_1.Get)('abandoned-carts/:id'),
213
+ (0, core_1.Allow)(core_1.Permission.ReadCustomer),
214
+ __param(0, (0, core_1.Ctx)()),
215
+ __param(1, (0, common_1.Param)('id')),
216
+ __metadata("design:type", Function),
217
+ __metadata("design:paramtypes", [core_1.RequestContext, String]),
218
+ __metadata("design:returntype", Promise)
219
+ ], AbandonedCartController.prototype, "detail", null);
220
+ __decorate([
221
+ (0, common_1.Post)('abandoned-carts/:id/recovery-link'),
222
+ (0, core_1.Allow)(core_1.Permission.UpdateCustomer),
223
+ __param(0, (0, core_1.Ctx)()),
224
+ __param(1, (0, common_1.Param)('id')),
225
+ __metadata("design:type", Function),
226
+ __metadata("design:paramtypes", [core_1.RequestContext, String]),
227
+ __metadata("design:returntype", Promise)
228
+ ], AbandonedCartController.prototype, "issueRecoveryLink", null);
229
+ __decorate([
230
+ (0, common_1.Post)('abandoned-carts/:id/status'),
231
+ (0, core_1.Allow)(core_1.Permission.UpdateCustomer),
232
+ __param(0, (0, core_1.Ctx)()),
233
+ __param(1, (0, common_1.Param)('id')),
234
+ __param(2, (0, common_1.Body)()),
235
+ __metadata("design:type", Function),
236
+ __metadata("design:paramtypes", [core_1.RequestContext, String, Object]),
237
+ __metadata("design:returntype", Promise)
238
+ ], AbandonedCartController.prototype, "setStatus", null);
239
+ __decorate([
240
+ (0, common_1.Get)('recover-cart'),
241
+ __param(0, (0, common_1.Req)()),
242
+ __param(1, (0, common_1.Query)('t')),
243
+ __metadata("design:type", Function),
244
+ __metadata("design:paramtypes", [Object, String]),
245
+ __metadata("design:returntype", Promise)
246
+ ], AbandonedCartController.prototype, "recover", null);
247
+ exports.AbandonedCartController = AbandonedCartController = __decorate([
248
+ (0, common_1.Controller)('ees'),
249
+ __metadata("design:paramtypes", [abandoned_cart_service_1.AbandonedCartService])
250
+ ], AbandonedCartController);
251
+ //# sourceMappingURL=abandoned-cart.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abandoned-cart.controller.js","sourceRoot":"","sources":["../src/abandoned-cart.controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ export type AbandonedCartStatus = 'abandoned' | 'recovered' | 'converted' | 'expired' | 'dismissed';
2
+ /**
3
+ * One row per abandoned cart, keyed on the visitor session that produced
4
+ * it. Rebuilt fresh from `cart_snapshot` events by the periodic scanner,
5
+ * so a session can be updated in-place until it either converts (order
6
+ * placed) or expires (recovery window elapses without any action).
7
+ */
8
+ export declare class AbandonedCart {
9
+ id: number;
10
+ visitorId: string;
11
+ sessionId: string;
12
+ /** Set when the visitor is signed in. Guest carts stay NULL and are
13
+ * matched to a customer only if they later sign in (via the same
14
+ * visitorId) or check out with a linkable email. */
15
+ customerId: number | null;
16
+ channelId: number;
17
+ currency: string;
18
+ /** Total value in the smallest currency unit (pence/cents). Storing
19
+ * minor units avoids float drift and matches Vendure's convention. */
20
+ totalMinor: number;
21
+ itemCount: number;
22
+ /** JSON array of cart items:
23
+ * [{ variantId, name, qty, unitPriceMinor, productId?, sku? }, …]
24
+ * Held as text because the recovery link needs to reconstruct the
25
+ * cart exactly — we don't want to join back to a live catalog that
26
+ * may have changed price by the time recovery is attempted. */
27
+ itemsJson: string;
28
+ /** Plain email if the storefront passed one (checkout step 1 usually
29
+ * captures this). NULL for cold browsers. */
30
+ email: string | null;
31
+ /** SHA-256 of the lowercased email — safe to keep even under
32
+ * aggressive privacy defaults, and used to link recurring sessions
33
+ * from the same buyer without exposing the raw address. */
34
+ emailHash: string | null;
35
+ firstSnapshotAt: Date;
36
+ lastSnapshotAt: Date;
37
+ /** Moment the scanner promoted the session from "active" to
38
+ * "abandoned" — i.e. no checkout_completed and no fresh
39
+ * cart_snapshot within the abandonment window. */
40
+ abandonedAt: Date;
41
+ recoveredAt: Date | null;
42
+ /** Signed opaque token that recovers the cart on the storefront.
43
+ * Regenerated by the admin/recover endpoint; time-bounded. */
44
+ recoveryToken: string | null;
45
+ recoveryTokenExpiresAt: Date | null;
46
+ status: AbandonedCartStatus;
47
+ recoveryOrderId: number | null;
48
+ lastKnownUrl: string | null;
49
+ lastKnownReferrer: string | null;
50
+ utmSource: string | null;
51
+ utmMedium: string | null;
52
+ utmCampaign: string | null;
53
+ countryCode: string | null;
54
+ /** True once we've fired the Slack / email notification for this
55
+ * abandonment. Prevents duplicate notifications when the scanner
56
+ * re-runs. */
57
+ notificationSent: boolean;
58
+ createdAt: Date;
59
+ updatedAt: Date;
60
+ }
61
+ //# sourceMappingURL=abandoned-cart.entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abandoned-cart.entity.d.ts","sourceRoot":"","sources":["../src/abandoned-cart.entity.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,mBAAmB,GACzB,WAAW,GACX,WAAW,GACX,WAAW,GACX,SAAS,GACT,WAAW,CAAC;AAElB;;;;;GAKG;AACH,qBAMa,aAAa;IAEtB,EAAE,EAAG,MAAM,CAAC;IAGZ,SAAS,EAAG,MAAM,CAAC;IAGnB,SAAS,EAAG,MAAM,CAAC;IAEnB;;yDAEqD;IAErD,UAAU,EAAG,MAAM,GAAG,IAAI,CAAC;IAG3B,SAAS,EAAG,MAAM,CAAC;IAGnB,QAAQ,EAAG,MAAM,CAAC;IAElB;2EACuE;IAEvE,UAAU,EAAG,MAAM,CAAC;IAGpB,SAAS,EAAG,MAAM,CAAC;IAEnB;;;;oEAIgE;IAEhE,SAAS,EAAG,MAAM,CAAC;IAEnB;kDAC8C;IAE9C,KAAK,EAAG,MAAM,GAAG,IAAI,CAAC;IAEtB;;gEAE4D;IAE5D,SAAS,EAAG,MAAM,GAAG,IAAI,CAAC;IAG1B,eAAe,EAAG,IAAI,CAAC;IAGvB,cAAc,EAAG,IAAI,CAAC;IAEtB;;uDAEmD;IAEnD,WAAW,EAAG,IAAI,CAAC;IAGnB,WAAW,EAAG,IAAI,GAAG,IAAI,CAAC;IAE1B;mEAC+D;IAE/D,aAAa,EAAG,MAAM,GAAG,IAAI,CAAC;IAG9B,sBAAsB,EAAG,IAAI,GAAG,IAAI,CAAC;IAGrC,MAAM,EAAG,mBAAmB,CAAC;IAG7B,eAAe,EAAG,MAAM,GAAG,IAAI,CAAC;IAGhC,YAAY,EAAG,MAAM,GAAG,IAAI,CAAC;IAG7B,iBAAiB,EAAG,MAAM,GAAG,IAAI,CAAC;IAGlC,SAAS,EAAG,MAAM,GAAG,IAAI,CAAC;IAG1B,SAAS,EAAG,MAAM,GAAG,IAAI,CAAC;IAG1B,WAAW,EAAG,MAAM,GAAG,IAAI,CAAC;IAG5B,WAAW,EAAG,MAAM,GAAG,IAAI,CAAC;IAE5B;;mBAEe;IAEf,gBAAgB,EAAG,OAAO,CAAC;IAG3B,SAAS,EAAG,IAAI,CAAC;IAGjB,SAAS,EAAG,IAAI,CAAC;CACpB"}