|
@@ -11,26 +11,32 @@ final class AppDependencies {
|
|
|
let searchInterpreter: OpenAISearchService
|
|
let searchInterpreter: OpenAISearchService
|
|
|
let validationService: JobValidationService
|
|
let validationService: JobValidationService
|
|
|
let searchPipeline: JobSearchPipeline
|
|
let searchPipeline: JobSearchPipeline
|
|
|
- let savedJobsStore: MockSavedJobsStore
|
|
|
|
|
|
|
+ let savedJobsStore: any SavedJobsStore
|
|
|
|
|
+ let savedJobsRevalidator: SavedJobsRevalidator
|
|
|
let alertsStore: MockAlertsStore
|
|
let alertsStore: MockAlertsStore
|
|
|
|
|
+ let persistenceController: PersistenceController?
|
|
|
|
|
|
|
|
init(
|
|
init(
|
|
|
jobDataSource: JobDataSource,
|
|
jobDataSource: JobDataSource,
|
|
|
searchInterpreter: OpenAISearchService,
|
|
searchInterpreter: OpenAISearchService,
|
|
|
validationService: JobValidationService,
|
|
validationService: JobValidationService,
|
|
|
searchPipeline: JobSearchPipeline,
|
|
searchPipeline: JobSearchPipeline,
|
|
|
- savedJobsStore: MockSavedJobsStore,
|
|
|
|
|
- alertsStore: MockAlertsStore
|
|
|
|
|
|
|
+ savedJobsStore: any SavedJobsStore,
|
|
|
|
|
+ savedJobsRevalidator: SavedJobsRevalidator,
|
|
|
|
|
+ alertsStore: MockAlertsStore,
|
|
|
|
|
+ persistenceController: PersistenceController? = nil
|
|
|
) {
|
|
) {
|
|
|
self.jobDataSource = jobDataSource
|
|
self.jobDataSource = jobDataSource
|
|
|
self.searchInterpreter = searchInterpreter
|
|
self.searchInterpreter = searchInterpreter
|
|
|
self.validationService = validationService
|
|
self.validationService = validationService
|
|
|
self.searchPipeline = searchPipeline
|
|
self.searchPipeline = searchPipeline
|
|
|
self.savedJobsStore = savedJobsStore
|
|
self.savedJobsStore = savedJobsStore
|
|
|
|
|
+ self.savedJobsRevalidator = savedJobsRevalidator
|
|
|
self.alertsStore = alertsStore
|
|
self.alertsStore = alertsStore
|
|
|
|
|
+ self.persistenceController = persistenceController
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// Preview / SwiftUI canvas — mocks only, no network.
|
|
|
|
|
|
|
+ /// Preview / SwiftUI canvas — mocks only, no network, in-memory saves.
|
|
|
static var preview: AppDependencies {
|
|
static var preview: AppDependencies {
|
|
|
let interpreter = MockSearchInterpreter()
|
|
let interpreter = MockSearchInterpreter()
|
|
|
let dataSource = MockJobDataSource()
|
|
let dataSource = MockJobDataSource()
|
|
@@ -45,18 +51,26 @@ final class AppDependencies {
|
|
|
validationService: validation,
|
|
validationService: validation,
|
|
|
cache: NullJobListingCache()
|
|
cache: NullJobListingCache()
|
|
|
)
|
|
)
|
|
|
|
|
+ let savedStore = MockSavedJobsStore()
|
|
|
|
|
+ let revalidator = SavedJobsRevalidator(
|
|
|
|
|
+ store: savedStore,
|
|
|
|
|
+ validationService: validation
|
|
|
|
|
+ )
|
|
|
return AppDependencies(
|
|
return AppDependencies(
|
|
|
jobDataSource: dataSource,
|
|
jobDataSource: dataSource,
|
|
|
searchInterpreter: interpreter,
|
|
searchInterpreter: interpreter,
|
|
|
validationService: validation,
|
|
validationService: validation,
|
|
|
searchPipeline: pipeline,
|
|
searchPipeline: pipeline,
|
|
|
- savedJobsStore: MockSavedJobsStore(),
|
|
|
|
|
- alertsStore: MockAlertsStore()
|
|
|
|
|
|
|
+ savedJobsStore: savedStore,
|
|
|
|
|
+ savedJobsRevalidator: revalidator,
|
|
|
|
|
+ alertsStore: MockAlertsStore(),
|
|
|
|
|
+ persistenceController: nil
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// App launch — OpenAI Responses + web_search (Indeed-only) for live job rows.
|
|
/// App launch — OpenAI Responses + web_search (Indeed-only) for live job rows.
|
|
|
/// Interpretation/ranking still use Chat Completions (gpt-6-luna) when available.
|
|
/// Interpretation/ranking still use Chat Completions (gpt-6-luna) when available.
|
|
|
|
|
+ /// Saved jobs persist via SwiftData; revalidation uses source signals + optional HEAD.
|
|
|
static var live: AppDependencies {
|
|
static var live: AppDependencies {
|
|
|
let mockInterpreter = MockSearchInterpreter()
|
|
let mockInterpreter = MockSearchInterpreter()
|
|
|
let heuristicRanking = HeuristicJobRankingService()
|
|
let heuristicRanking = HeuristicJobRankingService()
|
|
@@ -88,7 +102,8 @@ final class AppDependencies {
|
|
|
enrichmentSource = nil
|
|
enrichmentSource = nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- let validation = CompositeJobValidationService(
|
|
|
|
|
|
|
+ // Search pipeline: source signals only (avoid unsolicited HEAD during search).
|
|
|
|
|
+ let searchValidation = CompositeJobValidationService(
|
|
|
source: SourceSignalJobValidationService(),
|
|
source: SourceSignalJobValidationService(),
|
|
|
http: nil
|
|
http: nil
|
|
|
)
|
|
)
|
|
@@ -97,17 +112,32 @@ final class AppDependencies {
|
|
|
dataSource: primarySource,
|
|
dataSource: primarySource,
|
|
|
enrichmentDataSource: enrichmentSource,
|
|
enrichmentDataSource: enrichmentSource,
|
|
|
rankingService: ranking,
|
|
rankingService: ranking,
|
|
|
- validationService: validation,
|
|
|
|
|
|
|
+ validationService: searchValidation,
|
|
|
cache: InMemoryIndeedListingCache()
|
|
cache: InMemoryIndeedListingCache()
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+ // Saved jobs: source signal first, then lightweight HEAD when still unknown.
|
|
|
|
|
+ let savedValidation = CompositeJobValidationService(
|
|
|
|
|
+ source: SourceSignalJobValidationService(),
|
|
|
|
|
+ http: HTTPJobValidationService()
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ let persistence = PersistenceController.shared
|
|
|
|
|
+ let savedStore = SwiftDataSavedJobsStore(controller: persistence)
|
|
|
|
|
+ let revalidator = SavedJobsRevalidator(
|
|
|
|
|
+ store: savedStore,
|
|
|
|
|
+ validationService: savedValidation
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
return AppDependencies(
|
|
return AppDependencies(
|
|
|
jobDataSource: primarySource,
|
|
jobDataSource: primarySource,
|
|
|
searchInterpreter: interpreter,
|
|
searchInterpreter: interpreter,
|
|
|
- validationService: validation,
|
|
|
|
|
|
|
+ validationService: searchValidation,
|
|
|
searchPipeline: pipeline,
|
|
searchPipeline: pipeline,
|
|
|
- savedJobsStore: MockSavedJobsStore(),
|
|
|
|
|
- alertsStore: MockAlertsStore()
|
|
|
|
|
|
|
+ savedJobsStore: savedStore,
|
|
|
|
|
+ savedJobsRevalidator: revalidator,
|
|
|
|
|
+ alertsStore: MockAlertsStore(),
|
|
|
|
|
+ persistenceController: persistence
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|