From ea6e34c29808f08159b7de63346ab40645351194 Mon Sep 17 00:00:00 2001 From: vkumar-sonata Date: Tue, 21 Jul 2026 09:55:43 +0000 Subject: [PATCH 1/2] fix: add missing SiteConfig service override definitions --- types.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/types.ts b/types.ts index 62113472..303de828 100644 --- a/types.ts +++ b/types.ts @@ -59,6 +59,31 @@ export interface RequiredSiteConfig { export type LocalizedMessages = Record>; export type SiteMessages = LocalizedMessages[]; +// Generic logger contract +export interface LoggingService { + debug?(message: string, meta?: Record): void, + info?(message: string, meta?: Record): void, + warn?(message: string, meta?: Record): void, + error?(message: string | Error, meta?: Record): void, +} + +// Generic analytics contract +export interface AnalyticsService { + identify?(userId: string | number, traits?: Record): void, + track(event: string, properties?: Record): void, + page?(name?: string, properties?: Record): void, + reset?(): void, +} + +// Generic auth contract +export interface AuthService { + isAuthenticated(): boolean | Promise, + getAccessToken?(): string | null | Promise, + login?(redirectUrl?: string): void | Promise, + logout?(redirectUrl?: string): void | Promise, + getCurrentUser?(): User | null | Promise, +} + export interface OptionalSiteConfig { // Site environment environment: EnvironmentTypes, @@ -92,6 +117,11 @@ export interface OptionalSiteConfig { // Analytics segmentKey: string | null, + + // Services + loggingService: LoggingService, + analyticsService: AnalyticsService, + authService: AuthService, } export type SiteConfig = RequiredSiteConfig & Partial; From 3195cdc47fddaff9211cdeb766ced085d321586d Mon Sep 17 00:00:00 2001 From: vkumar-sonata Date: Thu, 6 Aug 2026 19:22:28 +0000 Subject: [PATCH 2/2] fix: correct service constructor types and add typecheck fixture --- eslint.config.js | 1 + runtime/analytics/types.ts | 7 +++ runtime/auth/types.ts | 13 +++++ ...site-config-service-overrides.typecheck.ts | 18 ++++++ types.ts | 57 +++++++++++-------- 5 files changed, 71 insertions(+), 25 deletions(-) create mode 100644 runtime/analytics/types.ts create mode 100644 runtime/auth/types.ts create mode 100644 test-types/site-config-service-overrides.typecheck.ts diff --git a/eslint.config.js b/eslint.config.js index 079f4afc..286f14ca 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -13,6 +13,7 @@ module.exports = tseslint.config( 'test-site/*', 'config/*', 'docs/*', + 'test-types/*', ], }, ); diff --git a/runtime/analytics/types.ts b/runtime/analytics/types.ts new file mode 100644 index 00000000..0d0a1769 --- /dev/null +++ b/runtime/analytics/types.ts @@ -0,0 +1,7 @@ +export interface AnalyticsService { + sendTrackingLogEvent(eventName: string, properties: object): Promise, + identifyAuthenticatedUser(userId: string | number, traits?: Record): void, + identifyAnonymousUser(traits?: Record): void, + sendTrackEvent(eventName?: string, properties?: Record): void, + sendPageEvent(category: string, name: string, properties?: Record): void, +} diff --git a/runtime/auth/types.ts b/runtime/auth/types.ts new file mode 100644 index 00000000..4a26d390 --- /dev/null +++ b/runtime/auth/types.ts @@ -0,0 +1,13 @@ +export interface AuthService { + getAuthenticatedHttpClient(options?: Record): unknown, + getHttpClient(options?: Record): unknown, + getLoginRedirectUrl(redirectUrl?: string): string, + redirectToLogin(redirectUrl?: string): void, + getLogoutRedirectUrl(redirectUrl?: string): string, + redirectToLogout(redirectUrl?: string): void, + getAuthenticatedUser(): Record | null, + setAuthenticatedUser(authUser: Record): void, + fetchAuthenticatedUser(options?: Record): Promise | null>, + ensureAuthenticatedUser(redirectUrl?: string): Promise>, + hydrateAuthenticatedUser(): Promise, +} diff --git a/test-types/site-config-service-overrides.typecheck.ts b/test-types/site-config-service-overrides.typecheck.ts new file mode 100644 index 00000000..c0b7bdd7 --- /dev/null +++ b/test-types/site-config-service-overrides.typecheck.ts @@ -0,0 +1,18 @@ +import { SiteConfig } from '../types'; +import NewRelicLoggingService from '../runtime/logging/NewRelicLoggingService'; +import SegmentAnalyticsService from '../runtime/analytics/SegmentAnalyticsService'; +import AxiosJwtAuthService from '../runtime/auth/AxiosJwtAuthService'; + +const config: SiteConfig = { + loggingService: NewRelicLoggingService, + analyticsService: SegmentAnalyticsService, + authService: AxiosJwtAuthService, + siteId: '', + siteName: '', + baseUrl: '', + lmsBaseUrl: '', + loginUrl: '', + logoutUrl: '', +} + +export default config; \ No newline at end of file diff --git a/types.ts b/types.ts index 303de828..62e62f97 100644 --- a/types.ts +++ b/types.ts @@ -2,6 +2,9 @@ import { FC, ReactElement, ReactNode } from 'react'; import { MessageDescriptor } from 'react-intl'; import { RouteObject } from 'react-router'; import { SlotOperation } from './runtime/slots/types'; +import { LoggingService } from './runtime/logging/types'; +import { AnalyticsService } from './runtime/analytics/types'; +import { AuthService } from './runtime/auth/types'; // Apps @@ -59,30 +62,34 @@ export interface RequiredSiteConfig { export type LocalizedMessages = Record>; export type SiteMessages = LocalizedMessages[]; -// Generic logger contract -export interface LoggingService { - debug?(message: string, meta?: Record): void, - info?(message: string, meta?: Record): void, - warn?(message: string, meta?: Record): void, - error?(message: string | Error, meta?: Record): void, -} +export type { LoggingService, AnalyticsService, AuthService }; -// Generic analytics contract -export interface AnalyticsService { - identify?(userId: string | number, traits?: Record): void, - track(event: string, properties?: Record): void, - page?(name?: string, properties?: Record): void, - reset?(): void, -} +// Logging instantiated +export type LoggingServiceClass = new (options: { + config: SiteConfig, +}) => LoggingService; -// Generic auth contract -export interface AuthService { - isAuthenticated(): boolean | Promise, - getAccessToken?(): string | null | Promise, - login?(redirectUrl?: string): void | Promise, - logout?(redirectUrl?: string): void | Promise, - getCurrentUser?(): User | null | Promise, -} +// Analytics instantiated +export type AnalyticsServiceClass = new (options: { + config: SiteConfig, + loggingService: LoggingService, + httpClient: unknown, +}) => AnalyticsService; + +// Auth instantiated +export type AuthServiceClass = new (options: { + config: { + baseUrl: string, + lmsBaseUrl: string, + loginUrl: string, + logoutUrl: string, + refreshAccessTokenApiPath: string, + accessTokenCookieName: string, + csrfTokenApiPath: string, + }, + loggingService: object, + middleware?: unknown[], +}) => AuthService; export interface OptionalSiteConfig { // Site environment @@ -119,9 +126,9 @@ export interface OptionalSiteConfig { segmentKey: string | null, // Services - loggingService: LoggingService, - analyticsService: AnalyticsService, - authService: AuthService, + loggingService: LoggingServiceClass, + analyticsService: AnalyticsServiceClass, + authService: AuthServiceClass, } export type SiteConfig = RequiredSiteConfig & Partial;