import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZoneChangeDetection, isDevMode } from '@angular/core'; import { provideRouter, withInMemoryScrolling } from '@angular/router'; import { provideHttpClient, withInterceptors, withXhr } from '@angular/common/http'; import { routes } from './app.routes'; import { cacheInterceptor } from './interceptors/cache.interceptor'; import { apiErrorInterceptor } from './core/interceptors/api-error.interceptor'; import { apiBaseUrlInterceptor } from './interceptors/api-base-url.interceptor'; import { apiHeadersInterceptor } from './interceptors/api-headers.interceptor'; import { mockDataInterceptor } from './interceptors/mock-data.interceptor'; import { adminAuthHeadersInterceptor, Ed25519VerificationService, NoopEd25519VerificationService, AUTH_API_URL, TELEGRAM_BOT_USERNAME } from '@marketplaces/auth'; import { provideMarketplacesPayment } from '@marketplaces/payment'; import { provideServiceWorker } from '@angular/service-worker'; import { MediaRepository } from './core/media/media-repository'; import { MockMediaRepository } from './core/media/mock-media-repository.service'; import { ApiConfigService } from './core/config/api-config.service'; import { TenantResolverService } from './core/config/tenant-resolver.service'; import { environment } from '../environments/environment'; export const appConfig: ApplicationConfig = { providers: [ provideBrowserGlobalErrorListeners(), provideZoneChangeDetection({ eventCoalescing: true }), provideRouter( routes, withInMemoryScrolling({ scrollPositionRestoration: 'top' }) ), provideHttpClient(withXhr(), // apiErrorInterceptor sits last so it observes the response after every // other interceptor has run, and normalizes whatever actually came back. withInterceptors([mockDataInterceptor, apiBaseUrlInterceptor, apiHeadersInterceptor, adminAuthHeadersInterceptor, cacheInterceptor, apiErrorInterceptor]) ), { provide: AUTH_API_URL, useFactory: (apiConfig: ApiConfigService) => apiConfig.getBaseUrl(), deps: [ApiConfigService] }, { provide: TELEGRAM_BOT_USERNAME, useValue: environment.telegramBot }, // useFactory, not useClass: @marketplaces/auth ships plain tsc output, not // Angular Package Format, so it carries no baked-in Ivy DI metadata for // this class. useClass forces Angular to JIT-compile it at runtime, which // throws when @angular/compiler isn't loaded (true for this build). A // factory sidesteps that - NoopEd25519VerificationService has zero // constructor deps, so this is a correct fix, not a workaround. // Real fix belongs in vitanovaPackages: publish with ng-packagr. { provide: Ed25519VerificationService, useFactory: () => new NoopEd25519VerificationService() }, { provide: MediaRepository, useClass: MockMediaRepository }, // apiUrl: environment.qrApiUrl ('https://qr.vitanova.network/api') is the // same "central payment service" the legacy /qr and // /card/{partnerId}/{orderId} endpoints already used (api.service.ts) - // one service shared across every tenant, unlike the per-tenant // AUTH_API_URL above. Stripped the trailing /api here: the package's own // default paymentsPath is '/api/v1/payments', so passing qrApiUrl // unchanged would double it to .../api/api/v1/payments. Confirmed by // reading the package's baseUrl() directly (apiUrl + paymentsPath, // simple concatenation, no de-dup) - not yet confirmed against a live // backend, since qrApiUrl's own /api suffix was never meant for this // package. Revisit once a real payment request has actually been made. // // marketplaceDomain: a plain closure, not TenantResolverService. // provideMarketplacesPayment runs outside the injector (it returns // EnvironmentProviders, called before DI exists), so inject(DOCUMENT) // isn't available here. The package evaluates this function lazily // inside PaymentMarketplaceContext, which IS a real injection context - // this closure just can't be one itself. Mirrors // TenantResolverService.getHostname() intentionally; if that method's // logic changes, this needs to change with it. provideMarketplacesPayment({ apiUrl: environment.qrApiUrl.replace(/\/api\/?$/, ''), marketplaceDomain: () => window.location.hostname.toLowerCase(), }), provideServiceWorker('ngsw-worker.js', { enabled: !isDevMode(), registrationStrategy: 'registerWhenStable:30000' }) ] };