wip
This commit is contained in:
@@ -1,16 +1,15 @@
|
|||||||
import { Module, ConsoleLogger } from '@nestjs/common';
|
import { Module, ConsoleLogger } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { AnalyticsService } from './analytics.service';
|
import { AnalyticsService } from './analytics.service';
|
||||||
import { AnalyticsController } from '../../presentation/analytics.controller';
|
import { AnalyticsController } from '../../presentation/analytics.controller';
|
||||||
import { RecordPageViewUseCase } from './record-page-view.use-case';
|
import { RecordPageViewUseCase } from './record-page-view.use-case';
|
||||||
import { RecordEngagementUseCase } from './record-engagement.use-case';
|
import { RecordEngagementUseCase } from './record-engagement.use-case';
|
||||||
import { IPageViewRepository } from '@gridpilot/analytics/domain/repositories/IPageViewRepository';
|
import { TypeOrmPageViewRepository } from '../../infrastructure/analytics/typeorm-page-view.repository';
|
||||||
import { IEngagementRepository } from '@gridpilot/analytics/domain/repositories/IEngagementRepository';
|
|
||||||
import { ILogger } from '@gridpilot/shared/logging/ILogger';
|
|
||||||
import { InMemoryPageViewRepository } from '../../infrastructure/analytics/in-memory-page-view.repository';
|
|
||||||
import { InMemoryEngagementRepository } from '../../infrastructure/analytics/in-memory-engagement.repository';
|
import { InMemoryEngagementRepository } from '../../infrastructure/analytics/in-memory-engagement.repository';
|
||||||
|
import { PageViewEntity } from '../../infrastructure/analytics/typeorm-page-view.entity';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [], // Removed TypeOrmModule as we are using in-memory repositories
|
imports: [TypeOrmModule.forFeature([PageViewEntity])],
|
||||||
controllers: [AnalyticsController],
|
controllers: [AnalyticsController],
|
||||||
providers: [
|
providers: [
|
||||||
AnalyticsService,
|
AnalyticsService,
|
||||||
@@ -18,7 +17,7 @@ import { InMemoryEngagementRepository } from '../../infrastructure/analytics/in-
|
|||||||
RecordEngagementUseCase,
|
RecordEngagementUseCase,
|
||||||
{
|
{
|
||||||
provide: 'IPageViewRepository',
|
provide: 'IPageViewRepository',
|
||||||
useClass: InMemoryPageViewRepository,
|
useClass: TypeOrmPageViewRepository,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: 'IEngagementRepository',
|
provide: 'IEngagementRepository',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { RecordPageViewUseCase, RecordPageViewInput, RecordPageViewOutput } from './record-page-view.use-case';
|
import { RecordPageViewUseCase, RecordPageViewInput, RecordPageViewOutput } from './record-page-view.use-case';
|
||||||
import { IPageViewRepository } from '@gridpilot/analytics/domain/repositories/IPageViewRepository';
|
import { IPageViewRepository } from '@gridpilot/analytics/application/repositories/IPageViewRepository';
|
||||||
import { ILogger } from '@gridpilot/shared/logging/ILogger';
|
import { ILogger } from '@gridpilot/shared/logging/ILogger';
|
||||||
import { PageView } from '@gridpilot/analytics/domain/entities/PageView';
|
import { PageView } from '@gridpilot/analytics/domain/entities/PageView';
|
||||||
import { EntityType, VisitorType } from '@gridpilot/analytics/domain/types/PageView';
|
import { EntityType, VisitorType } from '@gridpilot/analytics/domain/types/PageView';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { PageView, EntityType, VisitorType } from '@gridpilot/analytics/domain/entities/PageView';
|
import { PageView, EntityType, VisitorType } from '@gridpilot/analytics/domain/entities/PageView';
|
||||||
import type { IPageViewRepository } from '@gridpilot/analytics/domain/repositories/IPageViewRepository';
|
import type { IPageViewRepository } from '@gridpilot/analytics/application/repositories/IPageViewRepository';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InMemoryPageViewRepository implements IPageViewRepository {
|
export class InMemoryPageViewRepository implements IPageViewRepository {
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
import { PageViewMapper } from './PageViewMapper';
|
||||||
|
import { PageView } from '@gridpilot/analytics/domain/entities/PageView';
|
||||||
|
import { PageViewEntity } from '../typeorm-page-view.entity';
|
||||||
|
import { EntityType, VisitorType } from '@gridpilot/analytics/domain/types/PageView';
|
||||||
|
|
||||||
|
describe('PageViewMapper', () => {
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
const pageViewProps = {
|
||||||
|
id: 'test-id',
|
||||||
|
entityType: EntityType.LEAGUE,
|
||||||
|
entityId: 'entity-id',
|
||||||
|
visitorType: VisitorType.ANONYMOUS,
|
||||||
|
sessionId: 'session-id',
|
||||||
|
timestamp: now,
|
||||||
|
visitorId: 'visitor-id',
|
||||||
|
referrer: 'fart.com',
|
||||||
|
userAgent: 'Mozilla',
|
||||||
|
country: 'US',
|
||||||
|
durationMs: 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
const pageViewDomain = PageView.create(pageViewProps);
|
||||||
|
|
||||||
|
it('should correctly map a PageView domain entity to a PageViewEntity persistence entity', () => {
|
||||||
|
const pageViewEntity = PageViewMapper.toPersistence(pageViewDomain);
|
||||||
|
|
||||||
|
expect(pageViewEntity).toBeInstanceOf(PageViewEntity);
|
||||||
|
expect(pageViewEntity.id).toEqual(pageViewDomain.id);
|
||||||
|
expect(pageViewEntity.entityType).toEqual(pageViewDomain.entityType);
|
||||||
|
expect(pageViewEntity.entityId).toEqual(pageViewDomain.entityId);
|
||||||
|
expect(pageViewEntity.visitorType).toEqual(pageViewDomain.visitorType);
|
||||||
|
expect(pageViewEntity.sessionId).toEqual(pageViewDomain.sessionId);
|
||||||
|
expect(pageViewEntity.timestamp.toISOString()).toEqual(pageViewDomain.timestamp.toISOString());
|
||||||
|
expect(pageViewEntity.visitorId).toEqual(pageViewDomain.visitorId);
|
||||||
|
expect(pageViewEntity.referrer).toEqual(pageViewDomain.referrer);
|
||||||
|
expect(pageViewEntity.userAgent).toEqual(pageViewDomain.userAgent);
|
||||||
|
expect(pageViewEntity.country).toEqual(pageViewDomain.country);
|
||||||
|
expect(pageViewEntity.durationMs).toEqual(pageViewDomain.durationMs);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly map a PageViewEntity persistence entity to a PageView domain entity', () => {
|
||||||
|
const pageViewEntity = new PageViewEntity();
|
||||||
|
pageViewEntity.id = pageViewProps.id;
|
||||||
|
pageViewEntity.entityType = pageViewProps.entityType as any; // Cast as any because entityType is string in entity
|
||||||
|
pageViewEntity.entityId = pageViewProps.entityId;
|
||||||
|
pageViewEntity.visitorType = pageViewProps.visitorType as any;
|
||||||
|
pageViewEntity.sessionId = pageViewProps.sessionId;
|
||||||
|
pageViewEntity.timestamp = pageViewProps.timestamp;
|
||||||
|
pageViewEntity.visitorId = pageViewProps.visitorId;
|
||||||
|
pageViewEntity.referrer = pageViewProps.referrer;
|
||||||
|
pageViewEntity.userAgent = pageViewProps.userAgent;
|
||||||
|
pageViewEntity.country = pageViewProps.country;
|
||||||
|
pageViewEntity.durationMs = pageViewProps.durationMs;
|
||||||
|
|
||||||
|
const pageView = PageViewMapper.toDomain(pageViewEntity);
|
||||||
|
|
||||||
|
expect(pageView).toBeInstanceOf(PageView);
|
||||||
|
expect(pageView.id).toEqual(pageViewEntity.id);
|
||||||
|
expect(pageView.entityType).toEqual(pageViewEntity.entityType);
|
||||||
|
expect(pageView.entityId).toEqual(pageViewEntity.entityId);
|
||||||
|
expect(pageView.visitorType).toEqual(pageViewEntity.visitorType);
|
||||||
|
expect(pageView.sessionId).toEqual(pageViewEntity.sessionId);
|
||||||
|
expect(pageView.timestamp.toISOString()).toEqual(pageViewEntity.timestamp.toISOString());
|
||||||
|
expect(pageView.visitorId).toEqual(pageViewEntity.visitorId);
|
||||||
|
expect(pageView.referrer).toEqual(pageViewEntity.referrer);
|
||||||
|
expect(pageView.userAgent).toEqual(pageViewEntity.userAgent);
|
||||||
|
expect(pageView.country).toEqual(pageViewEntity.country);
|
||||||
|
expect(pageView.durationMs).toEqual(pageViewEntity.durationMs);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle optional properties correctly when mapping to persistence', () => {
|
||||||
|
const minimalProps = {
|
||||||
|
id: 'minimal-id',
|
||||||
|
entityType: EntityType.RACE,
|
||||||
|
entityId: 'minimal-entity',
|
||||||
|
visitorType: VisitorType.DRIVER,
|
||||||
|
sessionId: 'minimal-session',
|
||||||
|
timestamp: now,
|
||||||
|
};
|
||||||
|
const minimalDomain = PageView.create(minimalProps);
|
||||||
|
const entity = PageViewMapper.toPersistence(minimalDomain);
|
||||||
|
|
||||||
|
expect(entity.visitorId).toBeUndefined();
|
||||||
|
expect(entity.referrer).toBeUndefined();
|
||||||
|
expect(entity.userAgent).toBeUndefined();
|
||||||
|
expect(entity.country).toBeUndefined();
|
||||||
|
expect(entity.durationMs).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle optional properties correctly when mapping to domain', () => {
|
||||||
|
const minimalEntity = new PageViewEntity();
|
||||||
|
minimalEntity.id = 'minimal-id-entity';
|
||||||
|
minimalEntity.entityType = EntityType.RACE as any;
|
||||||
|
minimalEntity.entityId = 'minimal-entity-entity';
|
||||||
|
minimalEntity.visitorType = VisitorType.DRIVER as any;
|
||||||
|
minimalEntity.sessionId = 'minimal-session-entity';
|
||||||
|
minimalEntity.timestamp = now;
|
||||||
|
|
||||||
|
const domain = PageViewMapper.toDomain(minimalEntity);
|
||||||
|
|
||||||
|
expect(domain.visitorId).toBeUndefined();
|
||||||
|
expect(domain.referrer).toBeUndefined();
|
||||||
|
expect(domain.userAgent).toBeUndefined();
|
||||||
|
expect(domain.country).toBeUndefined();
|
||||||
|
expect(domain.durationMs).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { PageView } from '../../domain/entities/PageView';
|
||||||
|
import { PageViewEntity } from '../../../../apps/api/src/infrastructure/analytics/typeorm-page-view.entity';
|
||||||
|
import { EntityType, VisitorType } from '../../domain/types/PageView';
|
||||||
|
import { PageViewProps } from '../../domain/types/PageView';
|
||||||
|
|
||||||
|
export class PageViewMapper {
|
||||||
|
public static toDomain(entity: PageViewEntity): PageView {
|
||||||
|
const props: Omit<PageViewProps, 'timestamp'> & { timestamp?: Date } = {
|
||||||
|
id: entity.id,
|
||||||
|
entityType: entity.entityType as EntityType,
|
||||||
|
entityId: entity.entityId,
|
||||||
|
visitorType: entity.visitorType as VisitorType,
|
||||||
|
sessionId: entity.sessionId,
|
||||||
|
timestamp: entity.timestamp,
|
||||||
|
...(entity.visitorId !== undefined && entity.visitorId !== null ? { visitorId: entity.visitorId } : {}),
|
||||||
|
...(entity.referrer !== undefined && entity.referrer !== null ? { referrer: entity.referrer } : {}),
|
||||||
|
...(entity.userAgent !== undefined && entity.userAgent !== null ? { userAgent: entity.userAgent } : {}),
|
||||||
|
...(entity.country !== undefined && entity.country !== null ? { country: entity.country } : {}),
|
||||||
|
...(entity.durationMs !== undefined && entity.durationMs !== null ? { durationMs: entity.durationMs } : {}),
|
||||||
|
};
|
||||||
|
return PageView.create(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static toPersistence(domain: PageView): PageViewEntity {
|
||||||
|
const entity = new PageViewEntity();
|
||||||
|
entity.id = domain.id;
|
||||||
|
entity.entityType = domain.entityType;
|
||||||
|
entity.entityId = domain.entityId;
|
||||||
|
entity.visitorType = domain.visitorType;
|
||||||
|
entity.sessionId = domain.sessionId;
|
||||||
|
entity.timestamp = domain.timestamp;
|
||||||
|
if (domain.visitorId !== undefined) entity.visitorId = domain.visitorId;
|
||||||
|
if (domain.referrer !== undefined) entity.referrer = domain.referrer;
|
||||||
|
if (domain.userAgent !== undefined) entity.userAgent = domain.userAgent;
|
||||||
|
if (domain.country !== undefined) entity.country = domain.country;
|
||||||
|
if (domain.durationMs !== undefined) entity.durationMs = domain.durationMs;
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
import { Entity, PrimaryColumn, Column } from 'typeorm';
|
import { Entity, PrimaryColumn, Column } from 'typeorm';
|
||||||
import { EntityType, VisitorType } from '@gridpilot/analytics/domain/types/PageView';
|
|
||||||
|
|
||||||
@Entity('page_views')
|
@Entity('page_views')
|
||||||
export class PageViewEntity {
|
export class PageViewEntity {
|
||||||
@PrimaryColumn({ type: 'uuid' })
|
@PrimaryColumn({ type: 'uuid' })
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
@Column({ type: 'enum', enum: EntityType })
|
@Column({ type: 'enum', enum: ['league', 'driver', 'team', 'race', 'sponsor'] })
|
||||||
entityType: EntityType;
|
entityType: string;
|
||||||
|
|
||||||
@Column({ type: 'uuid' })
|
@Column({ type: 'uuid' })
|
||||||
entityId: string;
|
entityId: string;
|
||||||
@@ -15,8 +13,8 @@ export class PageViewEntity {
|
|||||||
@Column({ type: 'uuid', nullable: true })
|
@Column({ type: 'uuid', nullable: true })
|
||||||
visitorId?: string;
|
visitorId?: string;
|
||||||
|
|
||||||
@Column({ type: 'enum', enum: VisitorType })
|
@Column({ type: 'enum', enum: ['anonymous', 'driver', 'sponsor'] })
|
||||||
visitorType: VisitorType;
|
visitorType: string;
|
||||||
|
|
||||||
@Column({ type: 'uuid' })
|
@Column({ type: 'uuid' })
|
||||||
sessionId: string;
|
sessionId: string;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { TypeOrmPageViewRepository } from './typeorm-page-view.repository';
|
|||||||
import { PageViewEntity } from './typeorm-page-view.entity';
|
import { PageViewEntity } from './typeorm-page-view.entity';
|
||||||
import { PageView } from '@gridpilot/analytics/domain/entities/PageView';
|
import { PageView } from '@gridpilot/analytics/domain/entities/PageView';
|
||||||
import { EntityType, VisitorType } from '@gridpilot/analytics/domain/types/PageView';
|
import { EntityType, VisitorType } from '@gridpilot/analytics/domain/types/PageView';
|
||||||
import { IPageViewRepository } from '@gridpilot/analytics/domain/repositories/IPageViewRepository';
|
import { IPageViewRepository } from '@gridpilot/analytics/application/repositories/IPageViewRepository';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
|
|
||||||
describe('TypeOrmPageViewRepository (Integration)', () => {
|
describe('TypeOrmPageViewRepository (Integration)', () => {
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Repository, MoreThanOrEqual, Between } from 'typeorm';
|
import { Repository, MoreThanOrEqual, Between } from 'typeorm';
|
||||||
import { PageView, EntityType } from '@gridpilot/analytics/domain/entities/PageView';
|
import { IPageViewRepository } from '@gridpilot/analytics/application/repositories/IPageViewRepository';
|
||||||
import { IPageViewRepository } from '@gridpilot/analytics/domain/repositories/IPageViewRepository';
|
|
||||||
import { PageViewEntity } from './typeorm-page-view.entity';
|
import { PageViewEntity } from './typeorm-page-view.entity';
|
||||||
|
import { PageViewMapper } from './mappers/PageViewMapper';
|
||||||
|
import { PageView } from '@gridpilot/analytics/domain/entities/PageView';
|
||||||
|
import { EntityType } from '@gridpilot/analytics/domain/types/PageView';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TypeOrmPageViewRepository implements IPageViewRepository {
|
export class TypeOrmPageViewRepository implements IPageViewRepository {
|
||||||
@@ -13,7 +15,7 @@ export class TypeOrmPageViewRepository implements IPageViewRepository {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async save(pageView: PageView): Promise<void> {
|
async save(pageView: PageView): Promise<void> {
|
||||||
const pageViewEntity = this.toPageViewEntity(pageView);
|
const pageViewEntity = PageViewMapper.toPersistence(pageView);
|
||||||
await this.pageViewRepository.save(pageViewEntity);
|
await this.pageViewRepository.save(pageViewEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +23,7 @@ export class TypeOrmPageViewRepository implements IPageViewRepository {
|
|||||||
const entity = await this.pageViewRepository.findOne({
|
const entity = await this.pageViewRepository.findOne({
|
||||||
where: { id },
|
where: { id },
|
||||||
});
|
});
|
||||||
return entity ? this.toPageView(entity) : null;
|
return entity ? PageViewMapper.toDomain(entity) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async findByEntityId(entityType: EntityType, entityId: string): Promise<PageView[]> {
|
async findByEntityId(entityType: EntityType, entityId: string): Promise<PageView[]> {
|
||||||
@@ -29,7 +31,7 @@ export class TypeOrmPageViewRepository implements IPageViewRepository {
|
|||||||
where: { entityType, entityId },
|
where: { entityType, entityId },
|
||||||
order: { timestamp: 'DESC' },
|
order: { timestamp: 'DESC' },
|
||||||
});
|
});
|
||||||
return entities.map(this.toPageView);
|
return entities.map(PageViewMapper.toDomain);
|
||||||
}
|
}
|
||||||
|
|
||||||
async findByDateRange(startDate: Date, endDate: Date): Promise<PageView[]> {
|
async findByDateRange(startDate: Date, endDate: Date): Promise<PageView[]> {
|
||||||
@@ -37,7 +39,7 @@ export class TypeOrmPageViewRepository implements IPageViewRepository {
|
|||||||
where: { timestamp: Between(startDate, endDate) },
|
where: { timestamp: Between(startDate, endDate) },
|
||||||
order: { timestamp: 'DESC' },
|
order: { timestamp: 'DESC' },
|
||||||
});
|
});
|
||||||
return entities.map(this.toPageView);
|
return entities.map(PageViewMapper.toDomain);
|
||||||
}
|
}
|
||||||
|
|
||||||
async findBySession(sessionId: string): Promise<PageView[]> {
|
async findBySession(sessionId: string): Promise<PageView[]> {
|
||||||
@@ -45,7 +47,7 @@ export class TypeOrmPageViewRepository implements IPageViewRepository {
|
|||||||
where: { sessionId },
|
where: { sessionId },
|
||||||
order: { timestamp: 'DESC' },
|
order: { timestamp: 'DESC' },
|
||||||
});
|
});
|
||||||
return entities.map(this.toPageView);
|
return entities.map(PageViewMapper.toDomain);
|
||||||
}
|
}
|
||||||
|
|
||||||
async countByEntityId(entityType: EntityType, entityId: string, since?: Date): Promise<number> {
|
async countByEntityId(entityType: EntityType, entityId: string, since?: Date): Promise<number> {
|
||||||
@@ -69,36 +71,4 @@ export class TypeOrmPageViewRepository implements IPageViewRepository {
|
|||||||
const result = await query.getRawOne();
|
const result = await query.getRawOne();
|
||||||
return parseInt(result.count, 10) || 0;
|
return parseInt(result.count, 10) || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toPageViewEntity(pageView: PageView): PageViewEntity {
|
|
||||||
const entity = new PageViewEntity();
|
|
||||||
entity.id = pageView.id;
|
|
||||||
entity.entityType = pageView.entityType;
|
|
||||||
entity.entityId = pageView.entityId;
|
|
||||||
entity.visitorId = pageView.visitorId;
|
|
||||||
entity.visitorType = pageView.visitorType;
|
|
||||||
entity.sessionId = pageView.sessionId;
|
|
||||||
entity.referrer = pageView.referrer;
|
|
||||||
entity.userAgent = pageView.userAgent;
|
|
||||||
entity.country = pageView.country;
|
|
||||||
entity.timestamp = pageView.timestamp;
|
|
||||||
entity.durationMs = pageView.durationMs;
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private toPageView(entity: PageViewEntity): PageView {
|
|
||||||
return PageView.create({
|
|
||||||
id: entity.id,
|
|
||||||
entityType: entity.entityType,
|
|
||||||
entityId: entity.entityId,
|
|
||||||
visitorType: entity.visitorType,
|
|
||||||
sessionId: entity.sessionId,
|
|
||||||
timestamp: entity.timestamp,
|
|
||||||
visitorId: entity.visitorId,
|
|
||||||
referrer: entity.referrer,
|
|
||||||
userAgent: entity.userAgent,
|
|
||||||
country: entity.country,
|
|
||||||
durationMs: entity.durationMs,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es2017",
|
"target": "es2017",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
/**
|
import { PageView } from '../../domain/entities/PageView';
|
||||||
* Repository Interface: IPageViewRepository
|
import { EntityType } from '../../domain/types/PageView';
|
||||||
*
|
|
||||||
* Defines persistence operations for PageView entities.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import type { PageView, EntityType } from '../entities/PageView';
|
|
||||||
|
|
||||||
export interface IPageViewRepository {
|
export interface IPageViewRepository {
|
||||||
save(pageView: PageView): Promise<void>;
|
save(pageView: PageView): Promise<void>;
|
||||||
@@ -14,4 +9,4 @@ export interface IPageViewRepository {
|
|||||||
findBySession(sessionId: string): Promise<PageView[]>;
|
findBySession(sessionId: string): Promise<PageView[]>;
|
||||||
countByEntityId(entityType: EntityType, entityId: string, since?: Date): Promise<number>;
|
countByEntityId(entityType: EntityType, entityId: string, since?: Date): Promise<number>;
|
||||||
countUniqueVisitors(entityType: EntityType, entityId: string, since?: Date): Promise<number>;
|
countUniqueVisitors(entityType: EntityType, entityId: string, since?: Date): Promise<number>;
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.base.json",
|
"extends": "../../tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"rootDir": "src",
|
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"composite": false,
|
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"declarationMap": false
|
"declarationMap": false
|
||||||
},
|
},
|
||||||
"include": ["src"]
|
"include": ["**/*.ts"]
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"core/*",
|
"core/*",
|
||||||
"apps/*"
|
"apps/*",
|
||||||
|
"testing/*"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "echo 'Development server placeholder - to be configured'",
|
"dev": "echo 'Development server placeholder - to be configured'",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@gridpilot/testing-support",
|
"name": "@gridpilot/testing",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "./index.ts",
|
"main": "./index.ts",
|
||||||
9
testing/tsconfig.json
Normal file
9
testing/tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "dist",
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": false
|
||||||
|
},
|
||||||
|
"include": ["**/*.ts"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user