@carlonicora/nestjs-neo4jsonapi 4.14.0 → 4.15.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/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 +5 -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/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/package.json +1 -1
|
@@ -0,0 +1,490 @@
|
|
|
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.AnalyticsAdminRepository = exports.DIMENSIONS = exports.GRANULARITIES = exports.SECTIONS = void 0;
|
|
13
|
+
// nja-lint-ignore-file: cross-tenant administrative read repository.
|
|
14
|
+
//
|
|
15
|
+
// Every query here deliberately omits buildDefaultMatch(): that helper scopes to
|
|
16
|
+
// the CALLER's company via CLS, which is exactly wrong for a platform-wide admin
|
|
17
|
+
// dashboard — and the analytics labels are platform-level anyway
|
|
18
|
+
// (isCompanyScoped: false, no BELONGS_TO). Access is gated instead by the
|
|
19
|
+
// controller's JwtAuthGuard + @Roles(Administrator) (see
|
|
20
|
+
// analytics.admin.controller.ts). Rollup RETURNs are scalar columns, not graph
|
|
21
|
+
// nodes, so readOne()/readMany() cannot map them — entityFactory.createGraphList
|
|
22
|
+
// expects nodes. Same shape and same rationale as
|
|
23
|
+
// foundations/tokenusage/repositories/tokenusage.admin.repository.ts.
|
|
24
|
+
//
|
|
25
|
+
// For the same reason it also does NOT call Neo4jService.initQuery() — that
|
|
26
|
+
// helper prepends its own CLS-scoped company MATCH, which is the same scoping
|
|
27
|
+
// through a less obvious door. Every query here seeds itself from _adminQuery()
|
|
28
|
+
// instead; see that method for the outage it caused in the token-usage
|
|
29
|
+
// dashboard (ADM-53..57). No query here binds a parameter named `companyId`.
|
|
30
|
+
//
|
|
31
|
+
// The architecture gate raises a FILE-LEVEL manual-query-no-company-scope finding
|
|
32
|
+
// on this shape; per-line ignores do not clear it, so this header note is the
|
|
33
|
+
// documented resolution.
|
|
34
|
+
const common_1 = require("@nestjs/common");
|
|
35
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
36
|
+
const define_entity_1 = require("../../../common/helpers/define-entity");
|
|
37
|
+
const abstract_repository_1 = require("../../../core/neo4j/abstracts/abstract.repository");
|
|
38
|
+
const neo4j_service_1 = require("../../../core/neo4j/services/neo4j.service");
|
|
39
|
+
const security_service_1 = require("../../../core/security/services/security.service");
|
|
40
|
+
const analytics_daily_summary_meta_1 = require("../entities/analytics-daily-summary.meta");
|
|
41
|
+
const analytics_page_view_meta_1 = require("../entities/analytics-page-view.meta");
|
|
42
|
+
const analytics_session_1 = require("../entities/analytics-session");
|
|
43
|
+
const analytics_session_meta_1 = require("../entities/analytics-session.meta");
|
|
44
|
+
const analytics_timeline_1 = require("../entities/analytics-timeline");
|
|
45
|
+
/**
|
|
46
|
+
* The closed sets of values the admin endpoints accept. The controller
|
|
47
|
+
* validates query params against these tuples and the unions below are derived
|
|
48
|
+
* from them, so there is one declaration of each set.
|
|
49
|
+
*/
|
|
50
|
+
exports.SECTIONS = ["all", "public", "app"];
|
|
51
|
+
exports.GRANULARITIES = ["day", "week", "month"];
|
|
52
|
+
exports.DIMENSIONS = ["source", "medium", "campaign", "referrer", "route", "landing"];
|
|
53
|
+
const SESSION = analytics_session_meta_1.analyticsSessionMeta.nodeName; // "analyticsSession"
|
|
54
|
+
const PAGE_VIEW = analytics_page_view_meta_1.analyticsPageViewMeta.nodeName; // "analyticsPageView"
|
|
55
|
+
const SUMMARY = analytics_daily_summary_meta_1.analyticsDailySummaryMeta.nodeName; // "analyticsDailySummary"
|
|
56
|
+
/**
|
|
57
|
+
* The `date.truncate` units this repository is allowed to emit, keyed by the
|
|
58
|
+
* granularity it accepts. A lookup rather than a raw interpolation of the
|
|
59
|
+
* caller's string: nothing that did not come from this table can ever reach the
|
|
60
|
+
* query text.
|
|
61
|
+
*/
|
|
62
|
+
const TRUNCATION_UNITS = {
|
|
63
|
+
week: "week",
|
|
64
|
+
month: "month",
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* The section filter each accepted value binds. `all` binds nothing and adds no
|
|
68
|
+
* predicate; the other two are echoed from this table, never from the request.
|
|
69
|
+
*/
|
|
70
|
+
const SECTION_FILTERS = {
|
|
71
|
+
all: null,
|
|
72
|
+
public: "public",
|
|
73
|
+
app: "app",
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* The key expression each breakdown dimension may emit, and the label it reads.
|
|
77
|
+
* Session-based dimensions read the first page view's attribution stored on the
|
|
78
|
+
* session; `route` reads every page view. Missing attribution groups under
|
|
79
|
+
* `(none)` — the same key the nightly rollup writes, so raw and summarised rows
|
|
80
|
+
* merge on it.
|
|
81
|
+
*/
|
|
82
|
+
const DIMENSION_SPECS = {
|
|
83
|
+
source: { reads: "session", key: `coalesce(${SESSION}.utmSource, '(none)')` },
|
|
84
|
+
medium: { reads: "session", key: `coalesce(${SESSION}.utmMedium, '(none)')` },
|
|
85
|
+
campaign: { reads: "session", key: `coalesce(${SESSION}.utmCampaign, '(none)')` },
|
|
86
|
+
referrer: { reads: "session", key: `coalesce(${SESSION}.referrerHost, '(none)')` },
|
|
87
|
+
landing: { reads: "session", key: `coalesce(${SESSION}.landingRoute, '(none)')` },
|
|
88
|
+
route: { reads: "pageView", key: `coalesce(${PAGE_VIEW}.route, '(none)')` },
|
|
89
|
+
};
|
|
90
|
+
const toNumber = (v) => {
|
|
91
|
+
if (v === null || v === undefined)
|
|
92
|
+
return 0;
|
|
93
|
+
if (typeof v === "number")
|
|
94
|
+
return v;
|
|
95
|
+
if (typeof v.toNumber === "function")
|
|
96
|
+
return v.toNumber();
|
|
97
|
+
return Number(v) || 0;
|
|
98
|
+
};
|
|
99
|
+
const round = (v, dp) => {
|
|
100
|
+
const f = 10 ** dp;
|
|
101
|
+
return Math.round(v * f) / f;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Platform-wide reporting queries behind /analytics/administration/*.
|
|
105
|
+
*
|
|
106
|
+
* Extends AbstractRepository for the shared Neo4j/security/CLS plumbing and the
|
|
107
|
+
* descriptor typing; none of the inherited finders are used, for the reasons in
|
|
108
|
+
* the file header, and it deliberately does NOT override onModuleInit — the
|
|
109
|
+
* analytics indexes belong to the session, page-view and daily-summary
|
|
110
|
+
* repositories.
|
|
111
|
+
*
|
|
112
|
+
* Every aggregate is two reads merged in JS: the RAW part (sessions / page views
|
|
113
|
+
* on or after `retentionCutoff`) and the SUMMARISED part (daily summaries before
|
|
114
|
+
* it). Raw visitors are `count(DISTINCT visitorId)`; summarised visitors are the
|
|
115
|
+
* stored per-day distinct counts, summed — so a multi-day bucket over summarised
|
|
116
|
+
* data sums daily distinct visitors. The summary adds a third raw read for the
|
|
117
|
+
* cross-section visitor total (see _sectionTotals).
|
|
118
|
+
*/
|
|
119
|
+
let AnalyticsAdminRepository = class AnalyticsAdminRepository extends abstract_repository_1.AbstractRepository {
|
|
120
|
+
constructor(neo4j, securityService, clsService) {
|
|
121
|
+
super(neo4j, securityService, clsService);
|
|
122
|
+
this.descriptor = analytics_session_1.AnalyticsSessionDescriptor;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Six rows: {public, app, total} × {current, previous}. The previous window is
|
|
126
|
+
* the equal-length span immediately preceding `from`, which is what the KPI
|
|
127
|
+
* tiles' deltas are computed against.
|
|
128
|
+
*/
|
|
129
|
+
async findSummary(params) {
|
|
130
|
+
const section = this._section(params.section);
|
|
131
|
+
const previous = this._previousWindow(params.from, params.to);
|
|
132
|
+
const [current, prior] = await Promise.all([
|
|
133
|
+
this._sectionTotals({ from: params.from, to: params.to, section, retentionCutoff: params.retentionCutoff }),
|
|
134
|
+
this._sectionTotals({ from: previous.from, to: previous.to, section, retentionCutoff: params.retentionCutoff }),
|
|
135
|
+
]);
|
|
136
|
+
return [...this._withTotal(current, "current"), ...this._withTotal(prior, "previous")];
|
|
137
|
+
}
|
|
138
|
+
async findTimeline(params) {
|
|
139
|
+
const section = this._section(params.section);
|
|
140
|
+
// Cypher accepts a parameter for date.truncate's unit (verified against
|
|
141
|
+
// DozerDB 5.26), so the granularity is bound rather than interpolated —
|
|
142
|
+
// the "always parameterised, never interpolated" guardrail applies here
|
|
143
|
+
// even though _truncationUnit() already whitelists the value.
|
|
144
|
+
const granularity = params.granularity === "day" ? null : this._truncationUnit(params.granularity);
|
|
145
|
+
const seed = {
|
|
146
|
+
from: params.from,
|
|
147
|
+
to: params.to,
|
|
148
|
+
retentionCutoff: params.retentionCutoff,
|
|
149
|
+
section,
|
|
150
|
+
granularity,
|
|
151
|
+
};
|
|
152
|
+
const raw = this._adminQuery(seed);
|
|
153
|
+
const rawBucket = granularity === null ? `date(${SESSION}.startedAt)` : `date.truncate($granularity, ${SESSION}.startedAt)`;
|
|
154
|
+
raw.query = `
|
|
155
|
+
MATCH (${SESSION}:${analytics_session_meta_1.analyticsSessionMeta.labelName})
|
|
156
|
+
WHERE ${this._rawSessionWindow()}
|
|
157
|
+
${section === null ? "" : `AND ${SESSION}.section = $section`}
|
|
158
|
+
WITH ${rawBucket} AS bucket, ${SESSION}
|
|
159
|
+
RETURN bucket AS bucket,
|
|
160
|
+
count(DISTINCT ${SESSION}.visitorId) AS visitors,
|
|
161
|
+
count(${SESSION}) AS sessions,
|
|
162
|
+
sum(toInteger(${SESSION}.pageViews)) AS pageViews
|
|
163
|
+
ORDER BY bucket ASC
|
|
164
|
+
`;
|
|
165
|
+
const summarised = this._adminQuery(seed);
|
|
166
|
+
const summaryBucket = granularity === null ? `${SUMMARY}.date` : `date.truncate($granularity, ${SUMMARY}.date)`;
|
|
167
|
+
summarised.query = `
|
|
168
|
+
MATCH (${SUMMARY}:${analytics_daily_summary_meta_1.analyticsDailySummaryMeta.labelName} {dimension: 'total'})
|
|
169
|
+
WHERE ${this._summaryWindow()}
|
|
170
|
+
${section === null ? "" : `AND ${SUMMARY}.section = $section`}
|
|
171
|
+
WITH ${summaryBucket} AS bucket, ${SUMMARY}
|
|
172
|
+
RETURN bucket AS bucket,
|
|
173
|
+
sum(toInteger(${SUMMARY}.visitors)) AS visitors,
|
|
174
|
+
sum(toInteger(${SUMMARY}.sessions)) AS sessions,
|
|
175
|
+
sum(toInteger(${SUMMARY}.pageViews)) AS pageViews
|
|
176
|
+
ORDER BY bucket ASC
|
|
177
|
+
`;
|
|
178
|
+
const [rawResult, summaryResult] = await Promise.all([
|
|
179
|
+
this.neo4j.read(raw.query, raw.queryParams),
|
|
180
|
+
this.neo4j.read(summarised.query, summarised.queryParams),
|
|
181
|
+
]);
|
|
182
|
+
// The driver hands back a native Neo4j Date. convertFieldValue is the
|
|
183
|
+
// framework's single implementation of the descriptor-typed read-path
|
|
184
|
+
// conversion — the same one the auto-generated mapper() uses. Never
|
|
185
|
+
// toString() it in Cypher, never re-format it here. The field type is read
|
|
186
|
+
// off the descriptor so the two can never drift.
|
|
187
|
+
const bucketType = analytics_timeline_1.AnalyticsTimelineDescriptor.fields.bucket?.type ?? "date";
|
|
188
|
+
const merged = new Map();
|
|
189
|
+
for (const r of [...summaryResult.records, ...rawResult.records]) {
|
|
190
|
+
const bucketValue = (0, define_entity_1.convertFieldValue)(r.get("bucket"), bucketType);
|
|
191
|
+
merged.set(bucketValue, this._add(merged.get(bucketValue), this._metrics(r)));
|
|
192
|
+
}
|
|
193
|
+
return [...merged.entries()]
|
|
194
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
195
|
+
.map(([bucketValue, metrics]) => ({
|
|
196
|
+
id: `${bucketValue}|${params.section}`,
|
|
197
|
+
bucket: bucketValue,
|
|
198
|
+
section: params.section,
|
|
199
|
+
...metrics,
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Ranked rows, descending by visitors, truncated to `limit` with the exact
|
|
204
|
+
* remainder folded into a single "other" row. The full ordered set is fetched
|
|
205
|
+
* and sliced in JS so the remainder is exact rather than a second query's
|
|
206
|
+
* approximation.
|
|
207
|
+
*/
|
|
208
|
+
async findBreakdown(params) {
|
|
209
|
+
const section = this._section(params.section);
|
|
210
|
+
const { dimension, spec } = this._dimension(params.dimension);
|
|
211
|
+
const seed = { from: params.from, to: params.to, retentionCutoff: params.retentionCutoff, section, dimension };
|
|
212
|
+
const raw = this._adminQuery(seed);
|
|
213
|
+
if (spec.reads === "pageView") {
|
|
214
|
+
raw.query = `
|
|
215
|
+
MATCH (${PAGE_VIEW}:${analytics_page_view_meta_1.analyticsPageViewMeta.labelName})-[:IN_SESSION]->(${SESSION}:${analytics_session_meta_1.analyticsSessionMeta.labelName})
|
|
216
|
+
WHERE ${PAGE_VIEW}.createdAt >= datetime($from) AND ${PAGE_VIEW}.createdAt <= datetime($to)
|
|
217
|
+
AND date(${PAGE_VIEW}.createdAt) >= date($retentionCutoff)
|
|
218
|
+
${section === null ? "" : `AND ${PAGE_VIEW}.section = $section`}
|
|
219
|
+
WITH ${spec.key} AS key, ${PAGE_VIEW}, ${SESSION}
|
|
220
|
+
RETURN key AS key,
|
|
221
|
+
count(DISTINCT ${SESSION}.visitorId) AS visitors,
|
|
222
|
+
count(DISTINCT ${SESSION}) AS sessions,
|
|
223
|
+
count(${PAGE_VIEW}) AS pageViews
|
|
224
|
+
`;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
raw.query = `
|
|
228
|
+
MATCH (${SESSION}:${analytics_session_meta_1.analyticsSessionMeta.labelName})
|
|
229
|
+
WHERE ${this._rawSessionWindow()}
|
|
230
|
+
${section === null ? "" : `AND ${SESSION}.section = $section`}
|
|
231
|
+
WITH ${spec.key} AS key, ${SESSION}
|
|
232
|
+
RETURN key AS key,
|
|
233
|
+
count(DISTINCT ${SESSION}.visitorId) AS visitors,
|
|
234
|
+
count(${SESSION}) AS sessions,
|
|
235
|
+
sum(toInteger(${SESSION}.pageViews)) AS pageViews
|
|
236
|
+
`;
|
|
237
|
+
}
|
|
238
|
+
const summarised = this._adminQuery(seed);
|
|
239
|
+
summarised.query = `
|
|
240
|
+
MATCH (${SUMMARY}:${analytics_daily_summary_meta_1.analyticsDailySummaryMeta.labelName})
|
|
241
|
+
WHERE ${SUMMARY}.dimension = $dimension
|
|
242
|
+
AND ${this._summaryWindow()}
|
|
243
|
+
${section === null ? "" : `AND ${SUMMARY}.section = $section`}
|
|
244
|
+
RETURN ${SUMMARY}.key AS key,
|
|
245
|
+
sum(toInteger(${SUMMARY}.visitors)) AS visitors,
|
|
246
|
+
sum(toInteger(${SUMMARY}.sessions)) AS sessions,
|
|
247
|
+
sum(toInteger(${SUMMARY}.pageViews)) AS pageViews
|
|
248
|
+
`;
|
|
249
|
+
const [rawResult, summaryResult] = await Promise.all([
|
|
250
|
+
this.neo4j.read(raw.query, raw.queryParams),
|
|
251
|
+
this.neo4j.read(summarised.query, summarised.queryParams),
|
|
252
|
+
]);
|
|
253
|
+
const merged = new Map();
|
|
254
|
+
for (const r of [...rawResult.records, ...summaryResult.records]) {
|
|
255
|
+
const key = r.get("key") ?? "(none)";
|
|
256
|
+
merged.set(key, this._add(merged.get(key), this._metrics(r)));
|
|
257
|
+
}
|
|
258
|
+
const all = [...merged.entries()]
|
|
259
|
+
.sort(([ka, a], [kb, b]) => b.visitors - a.visitors || b.pageViews - a.pageViews || (ka < kb ? -1 : ka > kb ? 1 : 0))
|
|
260
|
+
.map(([key, metrics]) => ({ id: `${dimension}|${key}`, dimension, key, ...metrics }));
|
|
261
|
+
if (all.length <= params.limit)
|
|
262
|
+
return all;
|
|
263
|
+
const top = all.slice(0, params.limit);
|
|
264
|
+
const tail = all.slice(params.limit);
|
|
265
|
+
const other = {
|
|
266
|
+
id: `${dimension}|other`,
|
|
267
|
+
dimension,
|
|
268
|
+
key: "other",
|
|
269
|
+
visitors: tail.reduce((s, r) => s + r.visitors, 0),
|
|
270
|
+
sessions: tail.reduce((s, r) => s + r.sessions, 0),
|
|
271
|
+
pageViews: tail.reduce((s, r) => s + r.pageViews, 0),
|
|
272
|
+
};
|
|
273
|
+
return [...top, other];
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Raw + summarised totals split by section for one window, plus the window's
|
|
277
|
+
* total visitor count.
|
|
278
|
+
*
|
|
279
|
+
* `totalVisitors` cannot be the sum of the two sections: one visitor with
|
|
280
|
+
* sessions in both public and app would count twice. Its raw part is a third
|
|
281
|
+
* read with no section grouping (`count(DISTINCT visitorId)` across both); its
|
|
282
|
+
* summarised part is the stored per-day `total` rows summed, as for the
|
|
283
|
+
* sections, because summaries keep no visitor ids to de-duplicate.
|
|
284
|
+
*/
|
|
285
|
+
async _sectionTotals(params) {
|
|
286
|
+
const raw = this._adminQuery(params);
|
|
287
|
+
raw.query = `
|
|
288
|
+
MATCH (${SESSION}:${analytics_session_meta_1.analyticsSessionMeta.labelName})
|
|
289
|
+
WHERE ${this._rawSessionWindow()}
|
|
290
|
+
${params.section === null ? "" : `AND ${SESSION}.section = $section`}
|
|
291
|
+
RETURN ${SESSION}.section AS section,
|
|
292
|
+
count(DISTINCT ${SESSION}.visitorId) AS visitors,
|
|
293
|
+
count(DISTINCT CASE WHEN ${SESSION}.consented THEN ${SESSION}.visitorId END) AS consentedVisitors,
|
|
294
|
+
count(${SESSION}) AS sessions,
|
|
295
|
+
sum(toInteger(${SESSION}.pageViews)) AS pageViews
|
|
296
|
+
`;
|
|
297
|
+
const summarised = this._adminQuery(params);
|
|
298
|
+
summarised.query = `
|
|
299
|
+
MATCH (${SUMMARY}:${analytics_daily_summary_meta_1.analyticsDailySummaryMeta.labelName} {dimension: 'total'})
|
|
300
|
+
WHERE ${this._summaryWindow()}
|
|
301
|
+
${params.section === null ? "" : `AND ${SUMMARY}.section = $section`}
|
|
302
|
+
RETURN ${SUMMARY}.section AS section,
|
|
303
|
+
sum(toInteger(${SUMMARY}.visitors)) AS visitors,
|
|
304
|
+
sum(toInteger(${SUMMARY}.sessions)) AS sessions,
|
|
305
|
+
sum(toInteger(${SUMMARY}.pageViews)) AS pageViews
|
|
306
|
+
`;
|
|
307
|
+
const distinct = this._adminQuery(params);
|
|
308
|
+
distinct.query = `
|
|
309
|
+
MATCH (${SESSION}:${analytics_session_meta_1.analyticsSessionMeta.labelName})
|
|
310
|
+
WHERE ${this._rawSessionWindow()}
|
|
311
|
+
${params.section === null ? "" : `AND ${SESSION}.section = $section`}
|
|
312
|
+
RETURN count(DISTINCT ${SESSION}.visitorId) AS distinctVisitors
|
|
313
|
+
`;
|
|
314
|
+
const [rawResult, summaryResult, distinctResult] = await Promise.all([
|
|
315
|
+
this.neo4j.read(raw.query, raw.queryParams),
|
|
316
|
+
this.neo4j.read(summarised.query, summarised.queryParams),
|
|
317
|
+
this.neo4j.read(distinct.query, distinct.queryParams),
|
|
318
|
+
]);
|
|
319
|
+
let totalVisitors = distinctResult.records.reduce((sum, r) => sum + toNumber(r.get("distinctVisitors")), 0);
|
|
320
|
+
const bySection = new Map();
|
|
321
|
+
const entry = (section) => {
|
|
322
|
+
const existing = bySection.get(section);
|
|
323
|
+
if (existing)
|
|
324
|
+
return existing;
|
|
325
|
+
const created = { section, visitors: 0, sessions: 0, pageViews: 0, rawVisitors: 0, consentedVisitors: 0 };
|
|
326
|
+
bySection.set(section, created);
|
|
327
|
+
return created;
|
|
328
|
+
};
|
|
329
|
+
for (const r of rawResult.records) {
|
|
330
|
+
const row = entry(r.get("section"));
|
|
331
|
+
const metrics = this._metrics(r);
|
|
332
|
+
row.visitors += metrics.visitors;
|
|
333
|
+
row.sessions += metrics.sessions;
|
|
334
|
+
row.pageViews += metrics.pageViews;
|
|
335
|
+
row.rawVisitors += metrics.visitors;
|
|
336
|
+
row.consentedVisitors += toNumber(r.get("consentedVisitors"));
|
|
337
|
+
}
|
|
338
|
+
for (const r of summaryResult.records) {
|
|
339
|
+
const row = entry(r.get("section"));
|
|
340
|
+
const metrics = this._metrics(r);
|
|
341
|
+
row.visitors += metrics.visitors;
|
|
342
|
+
row.sessions += metrics.sessions;
|
|
343
|
+
row.pageViews += metrics.pageViews;
|
|
344
|
+
totalVisitors += metrics.visitors;
|
|
345
|
+
}
|
|
346
|
+
return { sections: [...bySection.values()], totalVisitors };
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Guarantees both sections are present (zero-filled when a window has no
|
|
350
|
+
* rows) and appends the "total" section, so the tiles never have to branch on
|
|
351
|
+
* a missing row. Total sessions and page views are the sections' sum; total
|
|
352
|
+
* visitors is the de-duplicated count from _sectionTotals. Consent share is
|
|
353
|
+
* measured on the raw part only: daily summaries carry no consent split.
|
|
354
|
+
*/
|
|
355
|
+
_withTotal(totals, window) {
|
|
356
|
+
const rows = totals.sections;
|
|
357
|
+
const find = (section) => rows.find((r) => r.section === section) ?? {
|
|
358
|
+
section,
|
|
359
|
+
visitors: 0,
|
|
360
|
+
sessions: 0,
|
|
361
|
+
pageViews: 0,
|
|
362
|
+
rawVisitors: 0,
|
|
363
|
+
consentedVisitors: 0,
|
|
364
|
+
};
|
|
365
|
+
const publicRow = find("public");
|
|
366
|
+
const appRow = find("app");
|
|
367
|
+
const total = {
|
|
368
|
+
section: "total",
|
|
369
|
+
visitors: totals.totalVisitors,
|
|
370
|
+
sessions: publicRow.sessions + appRow.sessions,
|
|
371
|
+
pageViews: publicRow.pageViews + appRow.pageViews,
|
|
372
|
+
rawVisitors: publicRow.rawVisitors + appRow.rawVisitors,
|
|
373
|
+
consentedVisitors: publicRow.consentedVisitors + appRow.consentedVisitors,
|
|
374
|
+
};
|
|
375
|
+
return [publicRow, appRow, total].map((r) => ({
|
|
376
|
+
id: `${r.section}|${window}`,
|
|
377
|
+
section: r.section,
|
|
378
|
+
window,
|
|
379
|
+
visitors: r.visitors,
|
|
380
|
+
sessions: r.sessions,
|
|
381
|
+
pageViews: r.pageViews,
|
|
382
|
+
pagesPerSession: r.sessions === 0 ? 0 : round(r.pageViews / r.sessions, 2),
|
|
383
|
+
consentShare: r.rawVisitors === 0 ? 0 : round(r.consentedVisitors / r.rawVisitors, 4),
|
|
384
|
+
}));
|
|
385
|
+
}
|
|
386
|
+
/** Raw sessions inside the request range and on or after the retention cutoff. */
|
|
387
|
+
_rawSessionWindow() {
|
|
388
|
+
return `${SESSION}.startedAt >= datetime($from) AND ${SESSION}.startedAt <= datetime($to)
|
|
389
|
+
AND date(${SESSION}.startedAt) >= date($retentionCutoff)`;
|
|
390
|
+
}
|
|
391
|
+
/** Summarised days inside the request range and before the retention cutoff. */
|
|
392
|
+
_summaryWindow() {
|
|
393
|
+
return `${SUMMARY}.date >= date(datetime($from)) AND ${SUMMARY}.date <= date(datetime($to))
|
|
394
|
+
AND ${SUMMARY}.date < date($retentionCutoff)`;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* The query seed every aggregation in this file MUST use.
|
|
398
|
+
*
|
|
399
|
+
* It deliberately does NOT call `Neo4jService.initQuery()`. initQuery()
|
|
400
|
+
* PREPENDS `MATCH (company:Company {id: $companyId})` (plus a currentUser
|
|
401
|
+
* match hanging off it) whenever the CALLER's CLS session carries a
|
|
402
|
+
* `companyId` — the same CLS scoping the file header explains this dashboard
|
|
403
|
+
* must not have, reintroduced through a less obvious door than
|
|
404
|
+
* buildDefaultMatch().
|
|
405
|
+
*
|
|
406
|
+
* Reachable only for an Administrator who ALSO belongs to a company (CLS has
|
|
407
|
+
* no companyId otherwise), which is exactly the dual-role shape the platform
|
|
408
|
+
* admin fixture — and real deployments — have. In the token-usage dashboard
|
|
409
|
+
* that prepended MATCH reduced every aggregation to zero rows and the
|
|
410
|
+
* zero-fill rendered a successful, empty page (ADM-53..57).
|
|
411
|
+
*
|
|
412
|
+
* Analytics nodes have no company at all, so this seed binds no `companyId`
|
|
413
|
+
* parameter of any kind. `section`, `granularity` and `dimension` are bound
|
|
414
|
+
* only when the caller supplies them, and only with values echoed from this
|
|
415
|
+
* file's lookup tables.
|
|
416
|
+
*/
|
|
417
|
+
_adminQuery(params) {
|
|
418
|
+
return {
|
|
419
|
+
query: "",
|
|
420
|
+
queryParams: {
|
|
421
|
+
from: params.from,
|
|
422
|
+
to: params.to,
|
|
423
|
+
retentionCutoff: params.retentionCutoff,
|
|
424
|
+
...(params.section === undefined || params.section === null ? {} : { section: params.section }),
|
|
425
|
+
...(params.granularity === undefined ? {} : { granularity: params.granularity }),
|
|
426
|
+
...(params.dimension === undefined ? {} : { dimension: params.dimension }),
|
|
427
|
+
},
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
/** The equal-length span immediately preceding `from`. */
|
|
431
|
+
_previousWindow(from, to) {
|
|
432
|
+
const fromMs = new Date(from).getTime();
|
|
433
|
+
const toMs = new Date(to).getTime();
|
|
434
|
+
const span = Math.max(0, toMs - fromMs);
|
|
435
|
+
return { from: new Date(fromMs - span).toISOString(), to: new Date(fromMs).toISOString() };
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Resolves a granularity to the `date.truncate` unit it may emit. Throws
|
|
439
|
+
* rather than interpolating anything the table does not know about.
|
|
440
|
+
*/
|
|
441
|
+
_truncationUnit(granularity) {
|
|
442
|
+
const unit = Object.prototype.hasOwnProperty.call(TRUNCATION_UNITS, granularity)
|
|
443
|
+
? TRUNCATION_UNITS[granularity]
|
|
444
|
+
: undefined;
|
|
445
|
+
if (!unit)
|
|
446
|
+
throw new common_1.BadRequestException(`Unsupported timeline granularity: ${granularity}`);
|
|
447
|
+
return unit;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Resolves the requested section to the value it binds (`null` for `all`).
|
|
451
|
+
* Returns the TABLE'S OWN string, never the caller's.
|
|
452
|
+
*/
|
|
453
|
+
_section(section) {
|
|
454
|
+
if (!Object.prototype.hasOwnProperty.call(SECTION_FILTERS, section))
|
|
455
|
+
throw new common_1.BadRequestException(`section must be one of ${Object.keys(SECTION_FILTERS).join(", ")}`);
|
|
456
|
+
return SECTION_FILTERS[section];
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Resolves the requested dimension against the whitelist. Returns the table's
|
|
460
|
+
* own key and expression, never the caller's string.
|
|
461
|
+
*/
|
|
462
|
+
_dimension(requested) {
|
|
463
|
+
const dimension = exports.DIMENSIONS.find((d) => d === requested);
|
|
464
|
+
if (!dimension)
|
|
465
|
+
throw new common_1.BadRequestException(`dimension must be one of ${exports.DIMENSIONS.join(", ")}`);
|
|
466
|
+
return { dimension, spec: DIMENSION_SPECS[dimension] };
|
|
467
|
+
}
|
|
468
|
+
_add(a, b) {
|
|
469
|
+
if (!a)
|
|
470
|
+
return { ...b };
|
|
471
|
+
return {
|
|
472
|
+
visitors: a.visitors + b.visitors,
|
|
473
|
+
sessions: a.sessions + b.sessions,
|
|
474
|
+
pageViews: a.pageViews + b.pageViews,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
_metrics(record) {
|
|
478
|
+
return {
|
|
479
|
+
visitors: toNumber(record.get("visitors")),
|
|
480
|
+
sessions: toNumber(record.get("sessions")),
|
|
481
|
+
pageViews: toNumber(record.get("pageViews")),
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
exports.AnalyticsAdminRepository = AnalyticsAdminRepository;
|
|
486
|
+
exports.AnalyticsAdminRepository = AnalyticsAdminRepository = __decorate([
|
|
487
|
+
(0, common_1.Injectable)(),
|
|
488
|
+
__metadata("design:paramtypes", [neo4j_service_1.Neo4jService, security_service_1.SecurityService, nestjs_cls_1.ClsService])
|
|
489
|
+
], AnalyticsAdminRepository);
|
|
490
|
+
//# sourceMappingURL=analytics.admin.repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.admin.repository.js","sourceRoot":"","sources":["../../../../src/foundations/analytics/repositories/analytics.admin.repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ClsService } from "nestjs-cls";
|
|
2
|
+
import { JsonApiService } from "../../../core/jsonapi/services/jsonapi.service";
|
|
3
|
+
import { AbstractService } from "../../../core/neo4j/abstracts/abstract.service";
|
|
4
|
+
import { AnalyticsSession, AnalyticsSessionDescriptor } from "../entities/analytics-session";
|
|
5
|
+
import { AnalyticsModuleConfig } from "../interfaces/analytics.config.interface";
|
|
6
|
+
import { AnalyticsPageViewRepository } from "../repositories/analytics-page-view.repository";
|
|
7
|
+
import { AnalyticsSessionRepository } from "../repositories/analytics-session.repository";
|
|
8
|
+
import { AnalyticsAdminRepository, Dimension, Granularity, Section } from "../repositories/analytics.admin.repository";
|
|
9
|
+
/**
|
|
10
|
+
* Serialises the platform-wide web analytics reports as JSON:API documents.
|
|
11
|
+
*
|
|
12
|
+
* Extends AbstractService over the AnalyticsSession descriptor and its
|
|
13
|
+
* repository, mirroring TokenUsageAdminService: the inherited CRUD is not
|
|
14
|
+
* reachable from any route on AnalyticsAdminController, but keeps the base
|
|
15
|
+
* class coherent. Summary, timeline and breakdown serialise with the
|
|
16
|
+
* AGGREGATE descriptors' models, because their rows are rollups, not nodes.
|
|
17
|
+
*
|
|
18
|
+
* JSON:API documents are built exclusively by the framework — nothing here
|
|
19
|
+
* hand-assembles a { data: { type, attributes } } object.
|
|
20
|
+
*/
|
|
21
|
+
export declare class AnalyticsAdminService extends AbstractService<AnalyticsSession, typeof AnalyticsSessionDescriptor.relationships> {
|
|
22
|
+
protected readonly analyticsSessionRepository: AnalyticsSessionRepository;
|
|
23
|
+
protected readonly analyticsAdminRepository: AnalyticsAdminRepository;
|
|
24
|
+
protected readonly analyticsPageViewRepository: AnalyticsPageViewRepository;
|
|
25
|
+
private readonly config;
|
|
26
|
+
protected readonly descriptor: import("../../..").EntityDescriptor<AnalyticsSession, {
|
|
27
|
+
user: {
|
|
28
|
+
model: import("../../..").DataMeta;
|
|
29
|
+
direction: "out";
|
|
30
|
+
relationship: string;
|
|
31
|
+
cardinality: "one";
|
|
32
|
+
required: false;
|
|
33
|
+
dtoKey: string;
|
|
34
|
+
};
|
|
35
|
+
}>;
|
|
36
|
+
constructor(jsonApiService: JsonApiService, analyticsSessionRepository: AnalyticsSessionRepository, clsService: ClsService, analyticsAdminRepository: AnalyticsAdminRepository, analyticsPageViewRepository: AnalyticsPageViewRepository, config: Required<AnalyticsModuleConfig>);
|
|
37
|
+
getSummary(params: {
|
|
38
|
+
from: string;
|
|
39
|
+
to: string;
|
|
40
|
+
section: Section;
|
|
41
|
+
}): Promise<any>;
|
|
42
|
+
getTimeline(params: {
|
|
43
|
+
from: string;
|
|
44
|
+
to: string;
|
|
45
|
+
section: Section;
|
|
46
|
+
granularity: Granularity;
|
|
47
|
+
}): Promise<any>;
|
|
48
|
+
getBreakdown(params: {
|
|
49
|
+
from: string;
|
|
50
|
+
to: string;
|
|
51
|
+
section: Section;
|
|
52
|
+
dimension: Dimension;
|
|
53
|
+
limit: number;
|
|
54
|
+
}): Promise<any>;
|
|
55
|
+
getSessions(params: {
|
|
56
|
+
query: any;
|
|
57
|
+
from: string;
|
|
58
|
+
to: string;
|
|
59
|
+
section: Section;
|
|
60
|
+
visitorId?: string;
|
|
61
|
+
userId?: string;
|
|
62
|
+
}): Promise<any>;
|
|
63
|
+
getSessionPageViews(params: {
|
|
64
|
+
sessionId: string;
|
|
65
|
+
}): Promise<any>;
|
|
66
|
+
/**
|
|
67
|
+
* ISO date (YYYY-MM-DD, UTC) `retentionMonths` before today. Raw events older
|
|
68
|
+
* than this are gone (rolled up into daily summaries), so it is the boundary
|
|
69
|
+
* between the two sources the aggregate queries read. Shared with the cron.
|
|
70
|
+
* The day is clamped to the target month's length (31 March − 1 month → 28/29 February).
|
|
71
|
+
*/
|
|
72
|
+
retentionCutoff(): string;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=analytics.admin.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.admin.service.d.ts","sourceRoot":"","sources":["../../../../src/foundations/analytics/services/analytics.admin.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,gDAAgD,CAAC;AAEhF,OAAO,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAC;AAGjF,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAG7F,OAAO,EAAoB,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACnG,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAC7F,OAAO,EAAE,0BAA0B,EAAE,MAAM,8CAA8C,CAAC;AAC1F,OAAO,EAAE,wBAAwB,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,4CAA4C,CAAC;AAEvH;;;;;;;;;;;GAWG;AACH,qBACa,qBAAsB,SAAQ,eAAe,CACxD,gBAAgB,EAChB,OAAO,0BAA0B,CAAC,aAAa,CAChD;IAKG,SAAS,CAAC,QAAQ,CAAC,0BAA0B,EAAE,0BAA0B;IAEzE,SAAS,CAAC,QAAQ,CAAC,wBAAwB,EAAE,wBAAwB;IACrE,SAAS,CAAC,QAAQ,CAAC,2BAA2B,EAAE,2BAA2B;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM;IARnD,SAAS,CAAC,QAAQ,CAAC,UAAU;;;;;;;;;OAA8B;gBAGzD,cAAc,EAAE,cAAc,EACX,0BAA0B,EAAE,0BAA0B,EACzE,UAAU,EAAE,UAAU,EACH,wBAAwB,EAAE,wBAAwB,EAClD,2BAA2B,EAAE,2BAA2B,EAChC,MAAM,EAAE,QAAQ,CAAC,qBAAqB,CAAC;IAK9E,UAAU,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAWhF,WAAW,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAY3G,YAAY,CAAC,MAAM,EAAE;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,EAAE,SAAS,CAAC;QACrB,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,GAAG,CAAC;IAaV,WAAW,CAAC,MAAM,EAAE;QACxB,KAAK,EAAE,GAAG,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,OAAO,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,GAAG,CAAC;IAeV,mBAAmB,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAUtE;;;;;OAKG;IACH,eAAe,IAAI,MAAM;CAU1B"}
|