@carlonicora/nestjs-neo4jsonapi 4.14.0 → 4.16.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.
- package/README.md +2 -0
- package/dist/bootstrap/app.module.factory.d.ts.map +1 -1
- package/dist/bootstrap/app.module.factory.js +1 -0
- package/dist/bootstrap/app.module.factory.js.map +1 -1
- package/dist/bootstrap/bootstrap.options.d.ts +22 -0
- package/dist/bootstrap/bootstrap.options.d.ts.map +1 -1
- package/dist/config/base.config.d.ts.map +1 -1
- package/dist/config/base.config.js +9 -0
- package/dist/config/base.config.js.map +1 -1
- package/dist/config/enums/queue.id.d.ts +1 -0
- package/dist/config/enums/queue.id.d.ts.map +1 -1
- package/dist/config/enums/queue.id.js +1 -0
- package/dist/config/enums/queue.id.js.map +1 -1
- package/dist/config/interfaces/base.config.interface.d.ts +2 -0
- package/dist/config/interfaces/base.config.interface.d.ts.map +1 -1
- package/dist/config/interfaces/config.analytics.interface.d.ts +13 -0
- package/dist/config/interfaces/config.analytics.interface.d.ts.map +1 -0
- package/dist/config/interfaces/config.analytics.interface.js +3 -0
- package/dist/config/interfaces/config.analytics.interface.js.map +1 -0
- package/dist/config/interfaces/config.s3.interface.d.ts +5 -0
- package/dist/config/interfaces/config.s3.interface.d.ts.map +1 -1
- package/dist/config/interfaces/index.d.ts +1 -0
- package/dist/config/interfaces/index.d.ts.map +1 -1
- package/dist/config/interfaces/index.js +1 -0
- package/dist/config/interfaces/index.js.map +1 -1
- package/dist/foundations/analytics/analytics.module.d.ts +39 -0
- package/dist/foundations/analytics/analytics.module.d.ts.map +1 -0
- package/dist/foundations/analytics/analytics.module.js +122 -0
- package/dist/foundations/analytics/analytics.module.js.map +1 -0
- package/dist/foundations/analytics/controllers/analytics.admin.controller.d.ts +32 -0
- package/dist/foundations/analytics/controllers/analytics.admin.controller.d.ts.map +1 -0
- package/dist/foundations/analytics/controllers/analytics.admin.controller.js +197 -0
- package/dist/foundations/analytics/controllers/analytics.admin.controller.js.map +1 -0
- package/dist/foundations/analytics/controllers/analytics.controller.d.ts +29 -0
- package/dist/foundations/analytics/controllers/analytics.controller.d.ts.map +1 -0
- package/dist/foundations/analytics/controllers/analytics.controller.js +85 -0
- package/dist/foundations/analytics/controllers/analytics.controller.js.map +1 -0
- package/dist/foundations/analytics/cron/analytics-retention.cron.d.ts +13 -0
- package/dist/foundations/analytics/cron/analytics-retention.cron.d.ts.map +1 -0
- package/dist/foundations/analytics/cron/analytics-retention.cron.js +61 -0
- package/dist/foundations/analytics/cron/analytics-retention.cron.js.map +1 -0
- package/dist/foundations/analytics/dtos/analytics-event.post.dto.d.ts +21 -0
- package/dist/foundations/analytics/dtos/analytics-event.post.dto.d.ts.map +1 -0
- package/dist/foundations/analytics/dtos/analytics-event.post.dto.js +105 -0
- package/dist/foundations/analytics/dtos/analytics-event.post.dto.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-breakdown.d.ts +17 -0
- package/dist/foundations/analytics/entities/analytics-breakdown.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-breakdown.js +18 -0
- package/dist/foundations/analytics/entities/analytics-breakdown.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-breakdown.meta.d.ts +3 -0
- package/dist/foundations/analytics/entities/analytics-breakdown.meta.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-breakdown.meta.js +10 -0
- package/dist/foundations/analytics/entities/analytics-breakdown.meta.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-daily-summary.d.ts +30 -0
- package/dist/foundations/analytics/entities/analytics-daily-summary.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-daily-summary.js +28 -0
- package/dist/foundations/analytics/entities/analytics-daily-summary.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-daily-summary.meta.d.ts +3 -0
- package/dist/foundations/analytics/entities/analytics-daily-summary.meta.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-daily-summary.meta.js +10 -0
- package/dist/foundations/analytics/entities/analytics-daily-summary.meta.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-event.meta.d.ts +8 -0
- package/dist/foundations/analytics/entities/analytics-event.meta.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-event.meta.js +15 -0
- package/dist/foundations/analytics/entities/analytics-event.meta.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-page-view.d.ts +39 -0
- package/dist/foundations/analytics/entities/analytics-page-view.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-page-view.js +38 -0
- package/dist/foundations/analytics/entities/analytics-page-view.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-page-view.meta.d.ts +3 -0
- package/dist/foundations/analytics/entities/analytics-page-view.meta.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-page-view.meta.js +10 -0
- package/dist/foundations/analytics/entities/analytics-page-view.meta.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-session.d.ts +52 -0
- package/dist/foundations/analytics/entities/analytics-session.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-session.js +47 -0
- package/dist/foundations/analytics/entities/analytics-session.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-session.meta.d.ts +3 -0
- package/dist/foundations/analytics/entities/analytics-session.meta.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-session.meta.js +10 -0
- package/dist/foundations/analytics/entities/analytics-session.meta.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-summary.d.ts +24 -0
- package/dist/foundations/analytics/entities/analytics-summary.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-summary.js +20 -0
- package/dist/foundations/analytics/entities/analytics-summary.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-summary.meta.d.ts +3 -0
- package/dist/foundations/analytics/entities/analytics-summary.meta.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-summary.meta.js +10 -0
- package/dist/foundations/analytics/entities/analytics-summary.meta.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-timeline.d.ts +20 -0
- package/dist/foundations/analytics/entities/analytics-timeline.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-timeline.js +18 -0
- package/dist/foundations/analytics/entities/analytics-timeline.js.map +1 -0
- package/dist/foundations/analytics/entities/analytics-timeline.meta.d.ts +3 -0
- package/dist/foundations/analytics/entities/analytics-timeline.meta.d.ts.map +1 -0
- package/dist/foundations/analytics/entities/analytics-timeline.meta.js +10 -0
- package/dist/foundations/analytics/entities/analytics-timeline.meta.js.map +1 -0
- package/dist/foundations/analytics/index.d.ts +27 -0
- package/dist/foundations/analytics/index.d.ts.map +1 -0
- package/dist/foundations/analytics/index.js +54 -0
- package/dist/foundations/analytics/index.js.map +1 -0
- package/dist/foundations/analytics/interfaces/analytics.config.interface.d.ts +80 -0
- package/dist/foundations/analytics/interfaces/analytics.config.interface.d.ts.map +1 -0
- package/dist/foundations/analytics/interfaces/analytics.config.interface.js +28 -0
- package/dist/foundations/analytics/interfaces/analytics.config.interface.js.map +1 -0
- package/dist/foundations/analytics/interfaces/analytics.page-view.input.d.ts +30 -0
- package/dist/foundations/analytics/interfaces/analytics.page-view.input.d.ts.map +1 -0
- package/dist/foundations/analytics/interfaces/analytics.page-view.input.js +3 -0
- package/dist/foundations/analytics/interfaces/analytics.page-view.input.js.map +1 -0
- package/dist/foundations/analytics/interfaces/analytics.resolved-page-view.d.ts +30 -0
- package/dist/foundations/analytics/interfaces/analytics.resolved-page-view.d.ts.map +1 -0
- package/dist/foundations/analytics/interfaces/analytics.resolved-page-view.js +3 -0
- package/dist/foundations/analytics/interfaces/analytics.resolved-page-view.js.map +1 -0
- package/dist/foundations/analytics/processors/analytics.processor.d.ts +33 -0
- package/dist/foundations/analytics/processors/analytics.processor.d.ts.map +1 -0
- package/dist/foundations/analytics/processors/analytics.processor.js +126 -0
- package/dist/foundations/analytics/processors/analytics.processor.js.map +1 -0
- package/dist/foundations/analytics/repositories/analytics-daily-summary.repository.d.ts +38 -0
- package/dist/foundations/analytics/repositories/analytics-daily-summary.repository.d.ts.map +1 -0
- package/dist/foundations/analytics/repositories/analytics-daily-summary.repository.js +142 -0
- package/dist/foundations/analytics/repositories/analytics-daily-summary.repository.js.map +1 -0
- package/dist/foundations/analytics/repositories/analytics-page-view.repository.d.ts +30 -0
- package/dist/foundations/analytics/repositories/analytics-page-view.repository.d.ts.map +1 -0
- package/dist/foundations/analytics/repositories/analytics-page-view.repository.js +62 -0
- package/dist/foundations/analytics/repositories/analytics-page-view.repository.js.map +1 -0
- package/dist/foundations/analytics/repositories/analytics-session.repository.d.ts +87 -0
- package/dist/foundations/analytics/repositories/analytics-session.repository.d.ts.map +1 -0
- package/dist/foundations/analytics/repositories/analytics-session.repository.js +261 -0
- package/dist/foundations/analytics/repositories/analytics-session.repository.js.map +1 -0
- package/dist/foundations/analytics/repositories/analytics.admin.repository.d.ts +145 -0
- package/dist/foundations/analytics/repositories/analytics.admin.repository.d.ts.map +1 -0
- package/dist/foundations/analytics/repositories/analytics.admin.repository.js +490 -0
- package/dist/foundations/analytics/repositories/analytics.admin.repository.js.map +1 -0
- package/dist/foundations/analytics/services/analytics.admin.service.d.ts +74 -0
- package/dist/foundations/analytics/services/analytics.admin.service.d.ts.map +1 -0
- package/dist/foundations/analytics/services/analytics.admin.service.js +126 -0
- package/dist/foundations/analytics/services/analytics.admin.service.js.map +1 -0
- package/dist/foundations/analytics/services/analytics.service.d.ts +31 -0
- package/dist/foundations/analytics/services/analytics.service.d.ts.map +1 -0
- package/dist/foundations/analytics/services/analytics.service.js +57 -0
- package/dist/foundations/analytics/services/analytics.service.js.map +1 -0
- package/dist/foundations/analytics/services/analytics.visitor-id.service.d.ts +34 -0
- package/dist/foundations/analytics/services/analytics.visitor-id.service.d.ts.map +1 -0
- package/dist/foundations/analytics/services/analytics.visitor-id.service.js +93 -0
- package/dist/foundations/analytics/services/analytics.visitor-id.service.js.map +1 -0
- package/dist/foundations/foundations.modules.d.ts +3 -0
- package/dist/foundations/foundations.modules.d.ts.map +1 -1
- package/dist/foundations/foundations.modules.js +3 -1
- package/dist/foundations/foundations.modules.js.map +1 -1
- package/dist/foundations/index.d.ts +1 -0
- package/dist/foundations/index.d.ts.map +1 -1
- package/dist/foundations/index.js +1 -0
- package/dist/foundations/index.js.map +1 -1
- package/dist/foundations/s3/services/s3.service.d.ts +0 -1
- package/dist/foundations/s3/services/s3.service.d.ts.map +1 -1
- package/dist/foundations/s3/services/s3.service.js +6 -6
- package/dist/foundations/s3/services/s3.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_ANALYTICS_CONFIG = exports.ANALYTICS_QUEUE = exports.ANALYTICS_CONFIG = exports.AnalyticsRetentionCron = exports.AnalyticsProcessor = exports.AnalyticsAdminService = exports.AnalyticsService = exports.AnalyticsVisitorIdService = exports.AnalyticsAdminRepository = exports.AnalyticsDailySummaryRepository = exports.AnalyticsPageViewRepository = exports.AnalyticsSessionRepository = exports.analyticsEventMeta = exports.analyticsBreakdownMeta = exports.AnalyticsBreakdownDescriptor = exports.analyticsTimelineMeta = exports.AnalyticsTimelineDescriptor = exports.analyticsSummaryMeta = exports.AnalyticsSummaryDescriptor = exports.analyticsDailySummaryMeta = exports.AnalyticsDailySummaryDescriptor = exports.analyticsPageViewMeta = exports.AnalyticsPageViewDescriptor = exports.analyticsSessionMeta = exports.AnalyticsSessionDescriptor = exports.AnalyticsModule = void 0;
|
|
4
|
+
var analytics_module_1 = require("./analytics.module");
|
|
5
|
+
Object.defineProperty(exports, "AnalyticsModule", { enumerable: true, get: function () { return analytics_module_1.AnalyticsModule; } });
|
|
6
|
+
var analytics_session_1 = require("./entities/analytics-session");
|
|
7
|
+
Object.defineProperty(exports, "AnalyticsSessionDescriptor", { enumerable: true, get: function () { return analytics_session_1.AnalyticsSessionDescriptor; } });
|
|
8
|
+
var analytics_session_meta_1 = require("./entities/analytics-session.meta");
|
|
9
|
+
Object.defineProperty(exports, "analyticsSessionMeta", { enumerable: true, get: function () { return analytics_session_meta_1.analyticsSessionMeta; } });
|
|
10
|
+
var analytics_page_view_1 = require("./entities/analytics-page-view");
|
|
11
|
+
Object.defineProperty(exports, "AnalyticsPageViewDescriptor", { enumerable: true, get: function () { return analytics_page_view_1.AnalyticsPageViewDescriptor; } });
|
|
12
|
+
var analytics_page_view_meta_1 = require("./entities/analytics-page-view.meta");
|
|
13
|
+
Object.defineProperty(exports, "analyticsPageViewMeta", { enumerable: true, get: function () { return analytics_page_view_meta_1.analyticsPageViewMeta; } });
|
|
14
|
+
var analytics_daily_summary_1 = require("./entities/analytics-daily-summary");
|
|
15
|
+
Object.defineProperty(exports, "AnalyticsDailySummaryDescriptor", { enumerable: true, get: function () { return analytics_daily_summary_1.AnalyticsDailySummaryDescriptor; } });
|
|
16
|
+
var analytics_daily_summary_meta_1 = require("./entities/analytics-daily-summary.meta");
|
|
17
|
+
Object.defineProperty(exports, "analyticsDailySummaryMeta", { enumerable: true, get: function () { return analytics_daily_summary_meta_1.analyticsDailySummaryMeta; } });
|
|
18
|
+
var analytics_summary_1 = require("./entities/analytics-summary");
|
|
19
|
+
Object.defineProperty(exports, "AnalyticsSummaryDescriptor", { enumerable: true, get: function () { return analytics_summary_1.AnalyticsSummaryDescriptor; } });
|
|
20
|
+
var analytics_summary_meta_1 = require("./entities/analytics-summary.meta");
|
|
21
|
+
Object.defineProperty(exports, "analyticsSummaryMeta", { enumerable: true, get: function () { return analytics_summary_meta_1.analyticsSummaryMeta; } });
|
|
22
|
+
var analytics_timeline_1 = require("./entities/analytics-timeline");
|
|
23
|
+
Object.defineProperty(exports, "AnalyticsTimelineDescriptor", { enumerable: true, get: function () { return analytics_timeline_1.AnalyticsTimelineDescriptor; } });
|
|
24
|
+
var analytics_timeline_meta_1 = require("./entities/analytics-timeline.meta");
|
|
25
|
+
Object.defineProperty(exports, "analyticsTimelineMeta", { enumerable: true, get: function () { return analytics_timeline_meta_1.analyticsTimelineMeta; } });
|
|
26
|
+
var analytics_breakdown_1 = require("./entities/analytics-breakdown");
|
|
27
|
+
Object.defineProperty(exports, "AnalyticsBreakdownDescriptor", { enumerable: true, get: function () { return analytics_breakdown_1.AnalyticsBreakdownDescriptor; } });
|
|
28
|
+
var analytics_breakdown_meta_1 = require("./entities/analytics-breakdown.meta");
|
|
29
|
+
Object.defineProperty(exports, "analyticsBreakdownMeta", { enumerable: true, get: function () { return analytics_breakdown_meta_1.analyticsBreakdownMeta; } });
|
|
30
|
+
var analytics_event_meta_1 = require("./entities/analytics-event.meta");
|
|
31
|
+
Object.defineProperty(exports, "analyticsEventMeta", { enumerable: true, get: function () { return analytics_event_meta_1.analyticsEventMeta; } });
|
|
32
|
+
var analytics_session_repository_1 = require("./repositories/analytics-session.repository");
|
|
33
|
+
Object.defineProperty(exports, "AnalyticsSessionRepository", { enumerable: true, get: function () { return analytics_session_repository_1.AnalyticsSessionRepository; } });
|
|
34
|
+
var analytics_page_view_repository_1 = require("./repositories/analytics-page-view.repository");
|
|
35
|
+
Object.defineProperty(exports, "AnalyticsPageViewRepository", { enumerable: true, get: function () { return analytics_page_view_repository_1.AnalyticsPageViewRepository; } });
|
|
36
|
+
var analytics_daily_summary_repository_1 = require("./repositories/analytics-daily-summary.repository");
|
|
37
|
+
Object.defineProperty(exports, "AnalyticsDailySummaryRepository", { enumerable: true, get: function () { return analytics_daily_summary_repository_1.AnalyticsDailySummaryRepository; } });
|
|
38
|
+
var analytics_admin_repository_1 = require("./repositories/analytics.admin.repository");
|
|
39
|
+
Object.defineProperty(exports, "AnalyticsAdminRepository", { enumerable: true, get: function () { return analytics_admin_repository_1.AnalyticsAdminRepository; } });
|
|
40
|
+
var analytics_visitor_id_service_1 = require("./services/analytics.visitor-id.service");
|
|
41
|
+
Object.defineProperty(exports, "AnalyticsVisitorIdService", { enumerable: true, get: function () { return analytics_visitor_id_service_1.AnalyticsVisitorIdService; } });
|
|
42
|
+
var analytics_service_1 = require("./services/analytics.service");
|
|
43
|
+
Object.defineProperty(exports, "AnalyticsService", { enumerable: true, get: function () { return analytics_service_1.AnalyticsService; } });
|
|
44
|
+
var analytics_admin_service_1 = require("./services/analytics.admin.service");
|
|
45
|
+
Object.defineProperty(exports, "AnalyticsAdminService", { enumerable: true, get: function () { return analytics_admin_service_1.AnalyticsAdminService; } });
|
|
46
|
+
var analytics_processor_1 = require("./processors/analytics.processor");
|
|
47
|
+
Object.defineProperty(exports, "AnalyticsProcessor", { enumerable: true, get: function () { return analytics_processor_1.AnalyticsProcessor; } });
|
|
48
|
+
var analytics_retention_cron_1 = require("./cron/analytics-retention.cron");
|
|
49
|
+
Object.defineProperty(exports, "AnalyticsRetentionCron", { enumerable: true, get: function () { return analytics_retention_cron_1.AnalyticsRetentionCron; } });
|
|
50
|
+
var analytics_config_interface_1 = require("./interfaces/analytics.config.interface");
|
|
51
|
+
Object.defineProperty(exports, "ANALYTICS_CONFIG", { enumerable: true, get: function () { return analytics_config_interface_1.ANALYTICS_CONFIG; } });
|
|
52
|
+
Object.defineProperty(exports, "ANALYTICS_QUEUE", { enumerable: true, get: function () { return analytics_config_interface_1.ANALYTICS_QUEUE; } });
|
|
53
|
+
Object.defineProperty(exports, "DEFAULT_ANALYTICS_CONFIG", { enumerable: true, get: function () { return analytics_config_interface_1.DEFAULT_ANALYTICS_CONFIG; } });
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/foundations/analytics/index.ts"],"names":[],"mappings":";;;AAAA,uDAAqD;AAA5C,mHAAA,eAAe,OAAA;AACxB,kEAIsC;AAFpC,+HAAA,0BAA0B,OAAA;AAG5B,4EAAyE;AAAhE,8HAAA,oBAAoB,OAAA;AAC7B,sEAIwC;AAFtC,kIAAA,2BAA2B,OAAA;AAG7B,gFAA4E;AAAnE,iIAAA,qBAAqB,OAAA;AAC9B,8EAI4C;AAF1C,0IAAA,+BAA+B,OAAA;AAGjC,wFAAoF;AAA3E,yIAAA,yBAAyB,OAAA;AAClC,kEAIsC;AAFpC,+HAAA,0BAA0B,OAAA;AAG5B,4EAAyE;AAAhE,8HAAA,oBAAoB,OAAA;AAC7B,oEAIuC;AAFrC,iIAAA,2BAA2B,OAAA;AAG7B,8EAA2E;AAAlE,gIAAA,qBAAqB,OAAA;AAC9B,sEAIwC;AAFtC,mIAAA,4BAA4B,OAAA;AAG9B,gFAA6E;AAApE,kIAAA,sBAAsB,OAAA;AAC/B,wEAAqE;AAA5D,0HAAA,kBAAkB,OAAA;AAC3B,4FAAyF;AAAhF,0IAAA,0BAA0B,OAAA;AACnC,gGAA4F;AAAnF,6IAAA,2BAA2B,OAAA;AACpC,wGAAoG;AAA3F,qJAAA,+BAA+B,OAAA;AACxC,wFAAqF;AAA5E,sIAAA,wBAAwB,OAAA;AACjC,wFAAoF;AAA3E,yIAAA,yBAAyB,OAAA;AAClC,kEAAgE;AAAvD,qHAAA,gBAAgB,OAAA;AACzB,8EAA2E;AAAlE,gIAAA,qBAAqB,OAAA;AAC9B,wEAAsE;AAA7D,yHAAA,kBAAkB,OAAA;AAC3B,4EAAyE;AAAhE,kIAAA,sBAAsB,OAAA;AAG/B,sFAKiD;AAH/C,8HAAA,gBAAgB,OAAA;AAChB,6HAAA,eAAe,OAAA;AACf,sIAAA,wBAAwB,OAAA"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration interface for the AnalyticsModule.
|
|
3
|
+
*
|
|
4
|
+
* The normal way to configure analytics is the environment: `ANALYTICS_ENABLED`,
|
|
5
|
+
* `ANALYTICS_RETENTION_MONTHS` and `ANALYTICS_SESSION_TIMEOUT_MINUTES`, read
|
|
6
|
+
* through `baseConfig.analytics`. Values passed here are an override and win
|
|
7
|
+
* over the environment. With the variable unset and no override, nothing is
|
|
8
|
+
* registered: no controller, no queue and no processor.
|
|
9
|
+
*/
|
|
10
|
+
export interface AnalyticsModuleConfig {
|
|
11
|
+
/**
|
|
12
|
+
* When true, the module registers the public event endpoint, the admin
|
|
13
|
+
* endpoints, the queue, the processor and the retention cron.
|
|
14
|
+
*
|
|
15
|
+
* Normally set through `ANALYTICS_ENABLED=true`; a value here overrides the
|
|
16
|
+
* environment. Default false: analytics collection is an app-visible
|
|
17
|
+
* behaviour change and must be opted into explicitly.
|
|
18
|
+
*
|
|
19
|
+
* @default false (env: ANALYTICS_ENABLED)
|
|
20
|
+
*/
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* How many months raw sessions and page views are kept before the retention
|
|
24
|
+
* cron rolls them up into daily summaries and deletes them.
|
|
25
|
+
*
|
|
26
|
+
* @default 13 (env: ANALYTICS_RETENTION_MONTHS)
|
|
27
|
+
*/
|
|
28
|
+
retentionMonths?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Inactivity window after which the next event from the same visitor starts
|
|
31
|
+
* a new session.
|
|
32
|
+
*
|
|
33
|
+
* @default 30 (env: ANALYTICS_SESSION_TIMEOUT_MINUTES)
|
|
34
|
+
*/
|
|
35
|
+
sessionTimeoutMinutes?: number;
|
|
36
|
+
/**
|
|
37
|
+
* BullMQ queue the producer (`AnalyticsService.track()`) enqueues onto.
|
|
38
|
+
*
|
|
39
|
+
* The module registers this queue itself (`BullModule.registerQueue`), so an
|
|
40
|
+
* app does not have to add it to its own queue configuration.
|
|
41
|
+
*
|
|
42
|
+
* NOTE: the worker side (`AnalyticsProcessor`) binds to `QueueId.ANALYTICS`
|
|
43
|
+
* through the `@Processor()` decorator, which BullMQ evaluates at class-decoration
|
|
44
|
+
* time and therefore cannot read from this config. Overriding `queueId` with a
|
|
45
|
+
* different value moves the producer only — the consuming app must then run its
|
|
46
|
+
* own worker for that queue. Every package processor has the same constraint
|
|
47
|
+
* (see `CompanyProcessor`, `HowToProcessor`, `ChunkProcessor`).
|
|
48
|
+
*
|
|
49
|
+
* @default QueueId.ANALYTICS ("analytics")
|
|
50
|
+
*/
|
|
51
|
+
queueId?: string;
|
|
52
|
+
/**
|
|
53
|
+
* BullMQ job name used for the enqueue/dispatch handshake between
|
|
54
|
+
* `AnalyticsService.track()` and `AnalyticsProcessor.process()`.
|
|
55
|
+
*
|
|
56
|
+
* Both sides read this same value, so an app may rename it freely (e.g. to
|
|
57
|
+
* match its own `JobName` enum) as long as it is configured once here.
|
|
58
|
+
*
|
|
59
|
+
* @default "analytics:pageView"
|
|
60
|
+
*/
|
|
61
|
+
jobName?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Injection token for the resolved analytics configuration.
|
|
65
|
+
* Always resolves to a `Required<AnalyticsModuleConfig>` (defaults merged in).
|
|
66
|
+
*/
|
|
67
|
+
export declare const ANALYTICS_CONFIG: unique symbol;
|
|
68
|
+
/**
|
|
69
|
+
* Injection token for the BullMQ queue the module was configured with.
|
|
70
|
+
*
|
|
71
|
+
* `@InjectQueue()` cannot be used directly because the queue name is only known
|
|
72
|
+
* at `forRoot()` time; the module aliases the configured BullMQ queue token onto
|
|
73
|
+
* this stable token instead.
|
|
74
|
+
*/
|
|
75
|
+
export declare const ANALYTICS_QUEUE: unique symbol;
|
|
76
|
+
/**
|
|
77
|
+
* Default configuration values.
|
|
78
|
+
*/
|
|
79
|
+
export declare const DEFAULT_ANALYTICS_CONFIG: Required<AnalyticsModuleConfig>;
|
|
80
|
+
//# sourceMappingURL=analytics.config.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.config.interface.d.ts","sourceRoot":"","sources":["../../../../src/foundations/analytics/interfaces/analytics.config.interface.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,eAA6B,CAAC;AAE3D;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,eAA4B,CAAC;AAEzD;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,qBAAqB,CAMpE,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_ANALYTICS_CONFIG = exports.ANALYTICS_QUEUE = exports.ANALYTICS_CONFIG = void 0;
|
|
4
|
+
const queue_id_1 = require("../../../config/enums/queue.id");
|
|
5
|
+
/**
|
|
6
|
+
* Injection token for the resolved analytics configuration.
|
|
7
|
+
* Always resolves to a `Required<AnalyticsModuleConfig>` (defaults merged in).
|
|
8
|
+
*/
|
|
9
|
+
exports.ANALYTICS_CONFIG = Symbol("ANALYTICS_CONFIG");
|
|
10
|
+
/**
|
|
11
|
+
* Injection token for the BullMQ queue the module was configured with.
|
|
12
|
+
*
|
|
13
|
+
* `@InjectQueue()` cannot be used directly because the queue name is only known
|
|
14
|
+
* at `forRoot()` time; the module aliases the configured BullMQ queue token onto
|
|
15
|
+
* this stable token instead.
|
|
16
|
+
*/
|
|
17
|
+
exports.ANALYTICS_QUEUE = Symbol("ANALYTICS_QUEUE");
|
|
18
|
+
/**
|
|
19
|
+
* Default configuration values.
|
|
20
|
+
*/
|
|
21
|
+
exports.DEFAULT_ANALYTICS_CONFIG = {
|
|
22
|
+
enabled: false,
|
|
23
|
+
retentionMonths: 13,
|
|
24
|
+
sessionTimeoutMinutes: 30,
|
|
25
|
+
queueId: queue_id_1.QueueId.ANALYTICS,
|
|
26
|
+
jobName: "analytics:pageView",
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=analytics.config.interface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.config.interface.js","sourceRoot":"","sources":["../../../../src/foundations/analytics/interfaces/analytics.config.interface.ts"],"names":[],"mappings":";;;AAAA,6DAAyD;AAqEzD;;;GAGG;AACU,QAAA,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAE3D;;;;;;GAMG;AACU,QAAA,eAAe,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAEzD;;GAEG;AACU,QAAA,wBAAwB,GAAoC;IACvE,OAAO,EAAE,KAAK;IACd,eAAe,EAAE,EAAE;IACnB,qBAAqB,EAAE,EAAE;IACzB,OAAO,EAAE,kBAAO,CAAC,SAAS;IAC1B,OAAO,EAAE,oBAAoB;CAC9B,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input accepted by `AnalyticsService.track()` and queued as the BullMQ job
|
|
3
|
+
* payload consumed by `AnalyticsProcessor`.
|
|
4
|
+
*
|
|
5
|
+
* `clientIp` and `userAgent` travel only as far as the worker: they are hashed
|
|
6
|
+
* into the daily visitor id and classified into a `deviceType`, then discarded.
|
|
7
|
+
* Neither ever reaches Neo4j.
|
|
8
|
+
*/
|
|
9
|
+
export interface AnalyticsPageViewInput {
|
|
10
|
+
path: string;
|
|
11
|
+
section: "public" | "app";
|
|
12
|
+
referrer?: string;
|
|
13
|
+
utmSource?: string;
|
|
14
|
+
utmMedium?: string;
|
|
15
|
+
utmCampaign?: string;
|
|
16
|
+
utmTerm?: string;
|
|
17
|
+
utmContent?: string;
|
|
18
|
+
/** UUID from the consent cookie; absent when the visitor has not consented. */
|
|
19
|
+
visitorId?: string;
|
|
20
|
+
screenWidth?: number;
|
|
21
|
+
/** First `X-Forwarded-For` hop or `request.ip`. Hashed in the worker, never stored. */
|
|
22
|
+
clientIp: string;
|
|
23
|
+
/** Hashed and classified in the worker, never stored. */
|
|
24
|
+
userAgent: string;
|
|
25
|
+
/** Set by `OptionalJwtAuthGuard` when the request carries a valid token. */
|
|
26
|
+
userId?: string;
|
|
27
|
+
/** ISO instant set by the controller when the request arrived. */
|
|
28
|
+
receivedAt: string;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=analytics.page-view.input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.page-view.input.d.ts","sourceRoot":"","sources":["../../../../src/foundations/analytics/interfaces/analytics.page-view.input.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;CACpB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.page-view.input.js","sourceRoot":"","sources":["../../../../src/foundations/analytics/interfaces/analytics.page-view.input.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input accepted by `AnalyticsSessionRepository.recordPageView()`.
|
|
3
|
+
*
|
|
4
|
+
* Built by `AnalyticsProcessor` from an `AnalyticsPageViewInput` once the
|
|
5
|
+
* visitor id is resolved, the route normalised and the user agent reduced to a
|
|
6
|
+
* `deviceType`. Optional values are `null` rather than `undefined` so they can
|
|
7
|
+
* be bound straight into Cypher parameters.
|
|
8
|
+
*/
|
|
9
|
+
export interface AnalyticsResolvedPageView {
|
|
10
|
+
/** `c:<uuid>` from the consent cookie or `d:<sha256>` daily hash. */
|
|
11
|
+
visitorId: string;
|
|
12
|
+
consented: boolean;
|
|
13
|
+
path: string;
|
|
14
|
+
/** `path` with UUID segments replaced by `:id`. */
|
|
15
|
+
route: string;
|
|
16
|
+
section: "public" | "app";
|
|
17
|
+
/** Hostname of the external referrer, `null` for internal or missing referrers. */
|
|
18
|
+
referrerHost: string | null;
|
|
19
|
+
utmSource: string | null;
|
|
20
|
+
utmMedium: string | null;
|
|
21
|
+
utmCampaign: string | null;
|
|
22
|
+
utmTerm: string | null;
|
|
23
|
+
utmContent: string | null;
|
|
24
|
+
deviceType: string;
|
|
25
|
+
userId: string | null;
|
|
26
|
+
/** ISO instant; becomes the page view's `createdAt` and the session's `lastSeenAt`. */
|
|
27
|
+
receivedAt: string;
|
|
28
|
+
sessionTimeoutMinutes: number;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=analytics.resolved-page-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.resolved-page-view.d.ts","sourceRoot":"","sources":["../../../../src/foundations/analytics/interfaces/analytics.resolved-page-view.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,yBAAyB;IACxC,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC1B,mFAAmF;IACnF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,uFAAuF;IACvF,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB,EAAE,MAAM,CAAC;CAC/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.resolved-page-view.js","sourceRoot":"","sources":["../../../../src/foundations/analytics/interfaces/analytics.resolved-page-view.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { WorkerHost } from "@nestjs/bullmq";
|
|
2
|
+
import { Job } from "bullmq";
|
|
3
|
+
import { ClsService } from "nestjs-cls";
|
|
4
|
+
import { AppLoggingService } from "../../../core/logging/services/logging.service";
|
|
5
|
+
import { AnalyticsModuleConfig } from "../interfaces/analytics.config.interface";
|
|
6
|
+
import { AnalyticsPageViewInput } from "../interfaces/analytics.page-view.input";
|
|
7
|
+
import { AnalyticsSessionRepository } from "../repositories/analytics-session.repository";
|
|
8
|
+
import { AnalyticsVisitorIdService } from "../services/analytics.visitor-id.service";
|
|
9
|
+
/**
|
|
10
|
+
* Worker-side of `AnalyticsService.track()`.
|
|
11
|
+
*
|
|
12
|
+
* The queue name must be a compile-time constant because `@Processor()` is
|
|
13
|
+
* evaluated at class-decoration time — the same constraint every other package
|
|
14
|
+
* processor lives with (CompanyProcessor, HowToProcessor, ChunkProcessor). The
|
|
15
|
+
* job name, by contrast, is read from `ANALYTICS_CONFIG` at construction
|
|
16
|
+
* time, so producer and consumer always agree on it.
|
|
17
|
+
*
|
|
18
|
+
* Concurrency 1 so two events from one visitor can never both create a session.
|
|
19
|
+
*/
|
|
20
|
+
export declare class AnalyticsProcessor extends WorkerHost {
|
|
21
|
+
private readonly logger;
|
|
22
|
+
private readonly repository;
|
|
23
|
+
private readonly visitorIds;
|
|
24
|
+
private readonly cls;
|
|
25
|
+
private readonly jobName;
|
|
26
|
+
private readonly sessionTimeoutMinutes;
|
|
27
|
+
constructor(logger: AppLoggingService, repository: AnalyticsSessionRepository, visitorIds: AnalyticsVisitorIdService, cls: ClsService, config: Required<AnalyticsModuleConfig>);
|
|
28
|
+
onError(job: Job): void;
|
|
29
|
+
process(job: Job<AnalyticsPageViewInput>): Promise<void>;
|
|
30
|
+
private normaliseRoute;
|
|
31
|
+
private referrerHost;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=analytics.processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.processor.d.ts","sourceRoot":"","sources":["../../../../src/foundations/analytics/processors/analytics.processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEtE,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gDAAgD,CAAC;AACnF,OAAO,EAAoB,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACnG,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AAEjF,OAAO,EAAE,0BAA0B,EAAE,MAAM,8CAA8C,CAAC;AAC1F,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AAQrF;;;;;;;;;;GAUG;AACH,qBACa,kBAAmB,SAAQ,UAAU;IAK9C,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG;IAPtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;gBAG5B,MAAM,EAAE,iBAAiB,EACzB,UAAU,EAAE,0BAA0B,EACtC,UAAU,EAAE,yBAAyB,EACrC,GAAG,EAAE,UAAU,EACN,MAAM,EAAE,QAAQ,CAAC,qBAAqB,CAAC;IAQnE,OAAO,CAAC,GAAG,EAAE,GAAG;IAIV,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,sBAAsB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAgD9D,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,YAAY;CAQrB"}
|
|
@@ -0,0 +1,126 @@
|
|
|
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.AnalyticsProcessor = void 0;
|
|
16
|
+
const bullmq_1 = require("@nestjs/bullmq");
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const bullmq_2 = require("bullmq");
|
|
19
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
20
|
+
const queue_id_1 = require("../../../config/enums/queue.id");
|
|
21
|
+
const logging_service_1 = require("../../../core/logging/services/logging.service");
|
|
22
|
+
const analytics_config_interface_1 = require("../interfaces/analytics.config.interface");
|
|
23
|
+
const analytics_session_repository_1 = require("../repositories/analytics-session.repository");
|
|
24
|
+
const analytics_visitor_id_service_1 = require("../services/analytics.visitor-id.service");
|
|
25
|
+
/**
|
|
26
|
+
* UUID v1–v5 path segment. Same regex as the web helper
|
|
27
|
+
* (`nextjs-jsonapi/src/features/analytics/lib/routeNormaliser.ts`).
|
|
28
|
+
*/
|
|
29
|
+
const UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
30
|
+
/**
|
|
31
|
+
* Worker-side of `AnalyticsService.track()`.
|
|
32
|
+
*
|
|
33
|
+
* The queue name must be a compile-time constant because `@Processor()` is
|
|
34
|
+
* evaluated at class-decoration time — the same constraint every other package
|
|
35
|
+
* processor lives with (CompanyProcessor, HowToProcessor, ChunkProcessor). The
|
|
36
|
+
* job name, by contrast, is read from `ANALYTICS_CONFIG` at construction
|
|
37
|
+
* time, so producer and consumer always agree on it.
|
|
38
|
+
*
|
|
39
|
+
* Concurrency 1 so two events from one visitor can never both create a session.
|
|
40
|
+
*/
|
|
41
|
+
let AnalyticsProcessor = class AnalyticsProcessor extends bullmq_1.WorkerHost {
|
|
42
|
+
constructor(logger, repository, visitorIds, cls, config) {
|
|
43
|
+
super();
|
|
44
|
+
this.logger = logger;
|
|
45
|
+
this.repository = repository;
|
|
46
|
+
this.visitorIds = visitorIds;
|
|
47
|
+
this.cls = cls;
|
|
48
|
+
this.jobName = config.jobName;
|
|
49
|
+
this.sessionTimeoutMinutes = config.sessionTimeoutMinutes;
|
|
50
|
+
}
|
|
51
|
+
onError(job) {
|
|
52
|
+
this.logger.error(`Analytics pageView failed (jobId=${job.id}): ${job.failedReason ?? "unknown"}`);
|
|
53
|
+
}
|
|
54
|
+
async process(job) {
|
|
55
|
+
if (job.name !== this.jobName) {
|
|
56
|
+
throw new Error(`Job ${job.name} not handled by AnalyticsProcessor`);
|
|
57
|
+
}
|
|
58
|
+
const input = job.data;
|
|
59
|
+
if (this.visitorIds.isBot(input.userAgent)) {
|
|
60
|
+
this.logger.debug(`analytics pageView dropped reason=bot path=${input.path}`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// The worker runs outside any HTTP request, so CLS is empty: seed it
|
|
64
|
+
// explicitly or SecurityService has no context to work from.
|
|
65
|
+
await this.cls.run(async () => {
|
|
66
|
+
this.cls.set("isAutomatedJob", true);
|
|
67
|
+
const { visitorId, consented } = await this.visitorIds.resolve({
|
|
68
|
+
visitorId: input.visitorId,
|
|
69
|
+
clientIp: input.clientIp,
|
|
70
|
+
userAgent: input.userAgent,
|
|
71
|
+
receivedAt: input.receivedAt,
|
|
72
|
+
});
|
|
73
|
+
const resolved = {
|
|
74
|
+
visitorId,
|
|
75
|
+
consented,
|
|
76
|
+
path: input.path,
|
|
77
|
+
route: this.normaliseRoute(input.path),
|
|
78
|
+
section: input.section,
|
|
79
|
+
referrerHost: this.referrerHost(input.referrer),
|
|
80
|
+
utmSource: input.utmSource ?? null,
|
|
81
|
+
utmMedium: input.utmMedium ?? null,
|
|
82
|
+
utmCampaign: input.utmCampaign ?? null,
|
|
83
|
+
utmTerm: input.utmTerm ?? null,
|
|
84
|
+
utmContent: input.utmContent ?? null,
|
|
85
|
+
deviceType: this.visitorIds.deviceType(input.userAgent),
|
|
86
|
+
userId: input.userId ?? null,
|
|
87
|
+
receivedAt: input.receivedAt,
|
|
88
|
+
sessionTimeoutMinutes: this.sessionTimeoutMinutes,
|
|
89
|
+
};
|
|
90
|
+
const { sessionId, created } = await this.repository.recordPageView(resolved);
|
|
91
|
+
this.logger.debug(`analytics pageView visitor=${visitorId} session=${sessionId} created=${created}`);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
normaliseRoute(path) {
|
|
95
|
+
return path
|
|
96
|
+
.split("/")
|
|
97
|
+
.map((segment) => (UUID_SEGMENT.test(segment) ? ":id" : segment))
|
|
98
|
+
.join("/");
|
|
99
|
+
}
|
|
100
|
+
referrerHost(referrer) {
|
|
101
|
+
if (!referrer)
|
|
102
|
+
return null;
|
|
103
|
+
try {
|
|
104
|
+
return new URL(referrer).hostname || null;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
exports.AnalyticsProcessor = AnalyticsProcessor;
|
|
112
|
+
__decorate([
|
|
113
|
+
(0, bullmq_1.OnWorkerEvent)("failed"),
|
|
114
|
+
__metadata("design:type", Function),
|
|
115
|
+
__metadata("design:paramtypes", [bullmq_2.Job]),
|
|
116
|
+
__metadata("design:returntype", void 0)
|
|
117
|
+
], AnalyticsProcessor.prototype, "onError", null);
|
|
118
|
+
exports.AnalyticsProcessor = AnalyticsProcessor = __decorate([
|
|
119
|
+
(0, bullmq_1.Processor)(queue_id_1.QueueId.ANALYTICS, { concurrency: 1 }),
|
|
120
|
+
__param(4, (0, common_1.Inject)(analytics_config_interface_1.ANALYTICS_CONFIG)),
|
|
121
|
+
__metadata("design:paramtypes", [logging_service_1.AppLoggingService,
|
|
122
|
+
analytics_session_repository_1.AnalyticsSessionRepository,
|
|
123
|
+
analytics_visitor_id_service_1.AnalyticsVisitorIdService,
|
|
124
|
+
nestjs_cls_1.ClsService, Object])
|
|
125
|
+
], AnalyticsProcessor);
|
|
126
|
+
//# sourceMappingURL=analytics.processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.processor.js","sourceRoot":"","sources":["../../../../src/foundations/analytics/processors/analytics.processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ClsService } from "nestjs-cls";
|
|
2
|
+
import { AbstractRepository } from "../../../core/neo4j/abstracts/abstract.repository";
|
|
3
|
+
import { Neo4jService } from "../../../core/neo4j/services/neo4j.service";
|
|
4
|
+
import { SecurityService } from "../../../core/security/services/security.service";
|
|
5
|
+
import { AnalyticsDailySummary, AnalyticsDailySummaryDescriptor } from "../entities/analytics-daily-summary";
|
|
6
|
+
/**
|
|
7
|
+
* Daily roll-ups written by the retention job before a day's raw sessions and
|
|
8
|
+
* page views are deleted. Platform-level, written outside HTTP/CLS context.
|
|
9
|
+
*
|
|
10
|
+
* The aggregate reads RETURN scalar columns, not graph nodes, so
|
|
11
|
+
* readOne()/readMany() cannot map them; they read the columns off the driver
|
|
12
|
+
* result, the same shape and rationale as TokenUsageAdminRepository.
|
|
13
|
+
*/
|
|
14
|
+
export declare class AnalyticsDailySummaryRepository extends AbstractRepository<AnalyticsDailySummary, typeof AnalyticsDailySummaryDescriptor.relationships> {
|
|
15
|
+
protected readonly descriptor: import("../../..").EntityDescriptor<AnalyticsDailySummary, {}>;
|
|
16
|
+
constructor(neo4j: Neo4jService, securityService: SecurityService, clsService: ClsService);
|
|
17
|
+
/** Adds the (date, dimension) index on top of the id constraint AbstractRepository creates from the descriptor. */
|
|
18
|
+
onModuleInit(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* MERGEs one row per (section, dimension, key) for the sessions that started
|
|
21
|
+
* on `date`: `total` plus source, medium, campaign, referrer and landing from
|
|
22
|
+
* the sessions, and route from their page views. Sessions without a value for
|
|
23
|
+
* a dimension (no UTM, no external referrer) are written under the key
|
|
24
|
+
* '(none)', the same key AnalyticsAdminRepository's breakdown uses for raw
|
|
25
|
+
* rows, so raw and summarised rows merge.
|
|
26
|
+
*
|
|
27
|
+
* Every property is set ON CREATE only, so an existing row is never
|
|
28
|
+
* overwritten. That keeps a re-run idempotent after a crash part-way through
|
|
29
|
+
* the raw delete: the next night's rollup sees only the sessions that
|
|
30
|
+
* survived, and a plain SET would replace the stored totals with those
|
|
31
|
+
* smaller counts.
|
|
32
|
+
* Returns the number of rows written.
|
|
33
|
+
*/
|
|
34
|
+
rollupDay(params: {
|
|
35
|
+
date: string;
|
|
36
|
+
}): Promise<number>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=analytics-daily-summary.repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-daily-summary.repository.d.ts","sourceRoot":"","sources":["../../../../src/foundations/analytics/repositories/analytics-daily-summary.repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mDAAmD,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,kDAAkD,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,+BAA+B,EAAE,MAAM,qCAAqC,CAAC;AA4B7G;;;;;;;GAOG;AACH,qBACa,+BAAgC,SAAQ,kBAAkB,CACrE,qBAAqB,EACrB,OAAO,+BAA+B,CAAC,aAAa,CACrD;IACC,SAAS,CAAC,QAAQ,CAAC,UAAU,iEAAmC;gBAEpD,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU;IAIzF,mHAAmH;IACpG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5C;;;;;;;;;;;;;;OAcG;IACG,SAAS,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CA6E3D"}
|
|
@@ -0,0 +1,142 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.AnalyticsDailySummaryRepository = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
15
|
+
const abstract_repository_1 = require("../../../core/neo4j/abstracts/abstract.repository");
|
|
16
|
+
const neo4j_service_1 = require("../../../core/neo4j/services/neo4j.service");
|
|
17
|
+
const security_service_1 = require("../../../core/security/services/security.service");
|
|
18
|
+
const analytics_daily_summary_1 = require("../entities/analytics-daily-summary");
|
|
19
|
+
const analytics_page_view_meta_1 = require("../entities/analytics-page-view.meta");
|
|
20
|
+
const analytics_session_meta_1 = require("../entities/analytics-session.meta");
|
|
21
|
+
const toNumber = (v) => {
|
|
22
|
+
if (v === null || v === undefined)
|
|
23
|
+
return 0;
|
|
24
|
+
if (typeof v === "number")
|
|
25
|
+
return v;
|
|
26
|
+
if (typeof v.toNumber === "function")
|
|
27
|
+
return v.toNumber();
|
|
28
|
+
return Number(v) || 0;
|
|
29
|
+
};
|
|
30
|
+
const S = analytics_session_meta_1.analyticsSessionMeta.nodeName; // "analyticsSession"
|
|
31
|
+
const PV = analytics_page_view_meta_1.analyticsPageViewMeta.nodeName; // "analyticsPageView"
|
|
32
|
+
/** Key for a session with no value for a dimension; must match AnalyticsAdminRepository's coalesce. */
|
|
33
|
+
const NONE_KEY = "(none)";
|
|
34
|
+
/**
|
|
35
|
+
* Daily roll-ups written by the retention job before a day's raw sessions and
|
|
36
|
+
* page views are deleted. Platform-level, written outside HTTP/CLS context.
|
|
37
|
+
*
|
|
38
|
+
* The aggregate reads RETURN scalar columns, not graph nodes, so
|
|
39
|
+
* readOne()/readMany() cannot map them; they read the columns off the driver
|
|
40
|
+
* result, the same shape and rationale as TokenUsageAdminRepository.
|
|
41
|
+
*/
|
|
42
|
+
let AnalyticsDailySummaryRepository = class AnalyticsDailySummaryRepository extends abstract_repository_1.AbstractRepository {
|
|
43
|
+
constructor(neo4j, securityService, clsService) {
|
|
44
|
+
super(neo4j, securityService, clsService);
|
|
45
|
+
this.descriptor = analytics_daily_summary_1.AnalyticsDailySummaryDescriptor;
|
|
46
|
+
}
|
|
47
|
+
/** Adds the (date, dimension) index on top of the id constraint AbstractRepository creates from the descriptor. */
|
|
48
|
+
async onModuleInit() {
|
|
49
|
+
await super.onModuleInit();
|
|
50
|
+
const { nodeName, labelName } = this.descriptor.model;
|
|
51
|
+
await this.neo4j.writeOne({
|
|
52
|
+
query: `CREATE INDEX ${nodeName}_date_dimension IF NOT EXISTS FOR (${nodeName}:${labelName}) ON (${nodeName}.date, ${nodeName}.dimension)`,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* MERGEs one row per (section, dimension, key) for the sessions that started
|
|
57
|
+
* on `date`: `total` plus source, medium, campaign, referrer and landing from
|
|
58
|
+
* the sessions, and route from their page views. Sessions without a value for
|
|
59
|
+
* a dimension (no UTM, no external referrer) are written under the key
|
|
60
|
+
* '(none)', the same key AnalyticsAdminRepository's breakdown uses for raw
|
|
61
|
+
* rows, so raw and summarised rows merge.
|
|
62
|
+
*
|
|
63
|
+
* Every property is set ON CREATE only, so an existing row is never
|
|
64
|
+
* overwritten. That keeps a re-run idempotent after a crash part-way through
|
|
65
|
+
* the raw delete: the next night's rollup sees only the sessions that
|
|
66
|
+
* survived, and a plain SET would replace the stored totals with those
|
|
67
|
+
* smaller counts.
|
|
68
|
+
* Returns the number of rows written.
|
|
69
|
+
*/
|
|
70
|
+
async rollupDay(params) {
|
|
71
|
+
const sessionResult = await this.neo4j.read(`
|
|
72
|
+
MATCH (${S}:${analytics_session_meta_1.analyticsSessionMeta.labelName})
|
|
73
|
+
WHERE date(${S}.startedAt) = date($date)
|
|
74
|
+
UNWIND [
|
|
75
|
+
['total', ''],
|
|
76
|
+
['source', coalesce(${S}.utmSource, $noneKey)],
|
|
77
|
+
['medium', coalesce(${S}.utmMedium, $noneKey)],
|
|
78
|
+
['campaign', coalesce(${S}.utmCampaign, $noneKey)],
|
|
79
|
+
['referrer', coalesce(${S}.referrerHost, $noneKey)],
|
|
80
|
+
['landing', coalesce(${S}.landingRoute, $noneKey)]
|
|
81
|
+
] AS pair
|
|
82
|
+
WITH ${S}, pair[0] AS dimension, pair[1] AS key
|
|
83
|
+
RETURN ${S}.section AS section,
|
|
84
|
+
dimension,
|
|
85
|
+
key,
|
|
86
|
+
count(DISTINCT ${S}.visitorId) AS visitors,
|
|
87
|
+
count(DISTINCT ${S}) AS sessions,
|
|
88
|
+
sum(${S}.pageViews) AS pageViews
|
|
89
|
+
`, { date: params.date, noneKey: NONE_KEY });
|
|
90
|
+
const pageViewResult = await this.neo4j.read(`
|
|
91
|
+
MATCH (${PV}:${analytics_page_view_meta_1.analyticsPageViewMeta.labelName})-[:IN_SESSION]->(${S}:${analytics_session_meta_1.analyticsSessionMeta.labelName})
|
|
92
|
+
WHERE date(${S}.startedAt) = date($date)
|
|
93
|
+
RETURN ${PV}.section AS section,
|
|
94
|
+
'route' AS dimension,
|
|
95
|
+
${PV}.route AS key,
|
|
96
|
+
count(DISTINCT ${S}.visitorId) AS visitors,
|
|
97
|
+
count(DISTINCT ${S}) AS sessions,
|
|
98
|
+
count(${PV}) AS pageViews
|
|
99
|
+
`, { date: params.date });
|
|
100
|
+
const rows = [...sessionResult.records, ...pageViewResult.records].map((r) => {
|
|
101
|
+
const section = r.get("section");
|
|
102
|
+
const dimension = r.get("dimension");
|
|
103
|
+
const key = r.get("key") ?? "";
|
|
104
|
+
return {
|
|
105
|
+
id: `${params.date}|${section}|${dimension}|${key}`,
|
|
106
|
+
section,
|
|
107
|
+
dimension,
|
|
108
|
+
key,
|
|
109
|
+
visitors: toNumber(r.get("visitors")),
|
|
110
|
+
sessions: toNumber(r.get("sessions")),
|
|
111
|
+
pageViews: toNumber(r.get("pageViews")),
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
if (rows.length === 0)
|
|
115
|
+
return 0;
|
|
116
|
+
const { nodeName, labelName } = this.descriptor.model;
|
|
117
|
+
const query = this.neo4j.initQuery();
|
|
118
|
+
query.queryParams = { ...query.queryParams, date: params.date, rows };
|
|
119
|
+
query.query = `
|
|
120
|
+
UNWIND $rows AS row
|
|
121
|
+
MERGE (${nodeName}:${labelName} {id: row.id})
|
|
122
|
+
ON CREATE SET
|
|
123
|
+
${nodeName}.date = date(left($date, 10)),
|
|
124
|
+
${nodeName}.section = row.section,
|
|
125
|
+
${nodeName}.dimension = row.dimension,
|
|
126
|
+
${nodeName}.key = row.key,
|
|
127
|
+
${nodeName}.visitors = row.visitors,
|
|
128
|
+
${nodeName}.sessions = row.sessions,
|
|
129
|
+
${nodeName}.pageViews = row.pageViews,
|
|
130
|
+
${nodeName}.createdAt = datetime(),
|
|
131
|
+
${nodeName}.updatedAt = datetime()
|
|
132
|
+
`;
|
|
133
|
+
await this.neo4j.writeOne(query);
|
|
134
|
+
return rows.length;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
exports.AnalyticsDailySummaryRepository = AnalyticsDailySummaryRepository;
|
|
138
|
+
exports.AnalyticsDailySummaryRepository = AnalyticsDailySummaryRepository = __decorate([
|
|
139
|
+
(0, common_1.Injectable)(),
|
|
140
|
+
__metadata("design:paramtypes", [neo4j_service_1.Neo4jService, security_service_1.SecurityService, nestjs_cls_1.ClsService])
|
|
141
|
+
], AnalyticsDailySummaryRepository);
|
|
142
|
+
//# sourceMappingURL=analytics-daily-summary.repository.js.map
|