@studyportals/fawkes 8.7.2 → 9.0.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.
Files changed (41) hide show
  1. package/README.md +176 -176
  2. package/dist/sitemap-generator-seo/index.d.ts +1 -1
  3. package/dist/src/common/FilterKeyToFilterTypeMap.d.ts +2 -0
  4. package/dist/src/common/FilterKeyToFilterTypeMap.js +14 -0
  5. package/dist/src/common/FilterTypeMap.d.ts +2 -0
  6. package/dist/src/common/FilterTypeMap.js +1 -0
  7. package/dist/src/organisations/SearchIndexabilityManager.js +1 -2
  8. package/dist/src/organisations/policies/RankedOrganisationsSeoIndexabilityPolicy.js +1 -1
  9. package/dist/src/organisations/policies/index.d.ts +0 -1
  10. package/dist/src/organisations/policies/index.js +0 -1
  11. package/dist/src/organisations/policies/our-picks/AreaAttendance.js +16 -14
  12. package/dist/src/organisations/policies/our-picks/CountryAttendance.js +15 -13
  13. package/dist/src/organisations/policies/ranked/RankedArea.js +1 -1
  14. package/dist/src/organisations/policies/ranked/RankedAreaDiscipline.d.ts +1 -0
  15. package/dist/src/organisations/policies/ranked/RankedAreaDiscipline.js +1 -0
  16. package/dist/src/organisations/policies/ranked/RankedAttendance.js +3 -1
  17. package/dist/src/organisations/policies/ranked/RankedAttendanceDiscipline.js +2 -1
  18. package/dist/src/organisations/policies/ranked/RankedContinent.js +3 -1
  19. package/dist/src/organisations/policies/ranked/RankedContinentAttendance.js +15 -13
  20. package/dist/src/organisations/policies/ranked/RankedCountry.js +3 -1
  21. package/dist/src/organisations/policies/ranked/RankedCountryAttendance.js +1 -0
  22. package/dist/src/organisations/policies/ranked/RankedCountryDiscipline.js +30 -14
  23. package/dist/src/organisations/policies/ranked/RankedDiscipline.js +14 -8
  24. package/dist/src/organisations/policies/ranked/RankedUnfiltered.js +10 -4
  25. package/dist/src/organisations/rules/MinimumAmountOfRankedResultsRule.d.ts +3 -4
  26. package/dist/src/organisations/rules/MinimumAmountOfRankedResultsRule.js +12 -8
  27. package/dist/src/organisations/types/IOrganisationsSitemapDependencies.d.ts +0 -2
  28. package/dist/src/programmes/policies/CountryAttendanceDegree.js +1 -1
  29. package/dist/src/programmes/policies/CountryDurationDegree.js +1 -1
  30. package/dist/src/programmes/policies/CountryEducationalForm.js +1 -1
  31. package/dist/src/programmes/policies/DegreeAttendanceTuitionFee.d.ts +1 -1
  32. package/dist/src/programmes/policies/DegreeAttendanceTuitionFee.js +6 -6
  33. package/dist/src/programmes/policies/DegreeContinentTuitionFee.d.ts +1 -1
  34. package/dist/src/programmes/policies/DegreeContinentTuitionFee.js +6 -6
  35. package/dist/src/programmes/policies/DegreeFormatTuitionFee.js +5 -5
  36. package/dist/src/programmes/policies/DisciplineCountryEducationalForm.js +1 -1
  37. package/dist/src/programmes/policies/DisciplineEducationalForm.js +1 -1
  38. package/dist/src/sitemap-generator/ISearchApiClient.d.ts +1 -0
  39. package/dist/src/sitemap-generator/OrganisationsSitemapUrlGeneratorManager.d.ts +1 -2
  40. package/dist/src/sitemap-generator/OrganisationsSitemapUrlGeneratorManager.js +2 -4
  41. package/package.json +106 -105
@@ -5,6 +5,7 @@ import { OnlyFiltersSelectedRule } from '../../../common/rules/OnlyFiltersSelect
5
5
  import { CountryPresenter } from '../../../presenters/CountryPresenter';
6
6
  import { DisciplinePresenter } from '../../../presenters/DisciplinePresenter';
7
7
  import { RankedOrganisationsSeoIndexabilityPolicy } from '../RankedOrganisationsSeoIndexabilityPolicy';
8
+ const DEFAULT_CONCURRENT_REQUESTS = 20; // Maximum number of concurrent requests to avoid rate limiting
8
9
  export class RankedCountryDiscipline extends RankedOrganisationsSeoIndexabilityPolicy {
9
10
  name = 'Ranked Country Discipline Policy';
10
11
  description = 'Determines which ranking-sorted pages at the intersection of country and discipline filters qualify for indexing based on search value.';
@@ -17,22 +18,37 @@ export class RankedCountryDiscipline extends RankedOrganisationsSeoIndexabilityP
17
18
  super(dependencies);
18
19
  }
19
20
  async generateUrls() {
20
- const countryFragments = CountryPresenter.getInstance().getFragments();
21
- const disciplineFragments = DisciplinePresenter.getInstance().getFragments();
22
- const paths = [];
23
- for (const country of countryFragments) {
24
- for (const discipline of disciplineFragments) {
25
- const filterKeyValues = new Map([
26
- [FilterKey.COUNTRY, [country.id]],
27
- [FilterKey.DISCIPLINES, [discipline.id]]
28
- ]);
29
- const result = await this.checkRulesForSitemap(filterKeyValues);
30
- if (result) {
31
- paths.push(this.getPathWithSortingOption(`${country.path}/${discipline.path}`));
32
- }
21
+ try {
22
+ const countryFragments = CountryPresenter.getInstance().getFragments();
23
+ const disciplineFragments = DisciplinePresenter.getInstance().getFragments();
24
+ const paths = [];
25
+ const configuredConcurrency = Number.parseInt(process.env.SITEMAP_COMBINATION_CONCURRENCY
26
+ || DEFAULT_CONCURRENT_REQUESTS.toString(), 10);
27
+ const concurrencyLimit = Math.max(1, configuredConcurrency); // Ensure at least 1
28
+ // Create all combinations
29
+ const combinations = countryFragments.flatMap(country => disciplineFragments.map(discipline => ({ country, discipline })));
30
+ // Process in batches to respect API rate limits
31
+ for (let i = 0; i < combinations.length; i += concurrencyLimit) {
32
+ const batch = combinations.slice(i, i + concurrencyLimit);
33
+ const results = await Promise.all(batch.map(async ({ country, discipline }) => {
34
+ const filterKeyValues = new Map([
35
+ [FilterKey.COUNTRY, [country.id]],
36
+ [FilterKey.DISCIPLINES, [discipline.id]]
37
+ ]);
38
+ const result = await this.checkRulesForSitemap(filterKeyValues);
39
+ if (result) {
40
+ return this.getPathWithSortingOption(`${country.path}/${discipline.path}`);
41
+ }
42
+ return null;
43
+ }));
44
+ paths.push(...results.filter((path) => path !== null));
33
45
  }
46
+ return paths;
47
+ }
48
+ catch (error) {
49
+ console.error('Error generating URLs for RankedCountryDiscipline:', error);
50
+ return [];
34
51
  }
35
- return paths;
36
52
  }
37
53
  get filterCombination() {
38
54
  return FilterCombinations.RANKED_DISCIPLINE_COUNTRY;
@@ -15,16 +15,22 @@ export class RankedDiscipline extends RankedOrganisationsSeoIndexabilityPolicy {
15
15
  super(dependencies);
16
16
  }
17
17
  async generateUrls() {
18
- const disciplineFragments = DisciplinePresenter.getInstance().getFragments();
19
- const paths = [];
20
- for (const discipline of disciplineFragments) {
21
- const filterKeyValues = new Map([[FilterKey.DISCIPLINES, [discipline.id]]]);
22
- const result = await this.checkRulesForSitemap(filterKeyValues);
23
- if (result) {
24
- paths.push(this.getPathWithSortingOption(discipline.path));
18
+ try {
19
+ const disciplineFragments = DisciplinePresenter.getInstance().getFragments();
20
+ const paths = [];
21
+ for (const discipline of disciplineFragments) {
22
+ const filterKeyValues = new Map([[FilterKey.DISCIPLINES, [discipline.id]]]);
23
+ const result = await this.checkRulesForSitemap(filterKeyValues);
24
+ if (result) {
25
+ paths.push(this.getPathWithSortingOption(discipline.path));
26
+ }
25
27
  }
28
+ return paths;
29
+ }
30
+ catch (error) {
31
+ console.error('Error generating URLs for RankedDiscipline:', error);
32
+ return [];
26
33
  }
27
- return paths;
28
34
  }
29
35
  get filterCombination() {
30
36
  return FilterCombinations.RANKED_DISCIPLINE;
@@ -9,11 +9,17 @@ export class RankedUnfiltered extends RankedOrganisationsSeoIndexabilityPolicy {
9
9
  super(dependencies);
10
10
  }
11
11
  async generateUrls() {
12
- const filterKeyValues = new Map([]);
13
- if (await this.checkRulesForSitemap(filterKeyValues)) {
14
- return [this.getPathWithSortingOption('')];
12
+ try {
13
+ const filterKeyValues = new Map([]);
14
+ if (await this.checkRulesForSitemap(filterKeyValues)) {
15
+ return [this.getPathWithSortingOption('')];
16
+ }
17
+ return [];
18
+ }
19
+ catch (error) {
20
+ console.error('Error generating URLs for RankedUnfiltered:', error);
21
+ return [];
15
22
  }
16
- return [];
17
23
  }
18
24
  get filterCombination() {
19
25
  return FilterCombinations.RANKED_UNFILTERED;
@@ -1,11 +1,10 @@
1
1
  import { IRule } from '../../common/IRule';
2
2
  import { IOrganisationSearchDependencies } from '../types/IOrganisationSearchDependencies';
3
- import { FilterKeyValuesMap } from '../../common/FilterKeyValuesMap';
4
- import { IRankingApiClient } from '../../sitemap-generator/IRankingApiClient';
3
+ import { FilterKeyValuesMap, ISearchApiClient } from '../../../sitemap-generator-seo';
5
4
  export declare class MinimumAmountOfRankedResultsRule implements IRule {
6
5
  private readonly minimumRankedResultsCount;
7
- private readonly rankingApiClient?;
8
- constructor(rankingApiClient?: IRankingApiClient);
6
+ private readonly searchApiClient?;
7
+ constructor(searchApiClient?: ISearchApiClient);
9
8
  forSearch(dependencies: IOrganisationSearchDependencies): Promise<boolean>;
10
9
  forSitemapGenerator(filterKeyValues: FilterKeyValuesMap): Promise<boolean>;
11
10
  getName(): string;
@@ -1,9 +1,9 @@
1
1
  import { DependencyMissingError } from '../../errors/DependencyMissingError';
2
2
  export class MinimumAmountOfRankedResultsRule {
3
- minimumRankedResultsCount = 7;
4
- rankingApiClient;
5
- constructor(rankingApiClient) {
6
- this.rankingApiClient = rankingApiClient;
3
+ minimumRankedResultsCount = 4;
4
+ searchApiClient;
5
+ constructor(searchApiClient) {
6
+ this.searchApiClient = searchApiClient;
7
7
  }
8
8
  forSearch(dependencies) {
9
9
  const { applicationState } = dependencies;
@@ -11,14 +11,18 @@ export class MinimumAmountOfRankedResultsRule {
11
11
  return Promise.resolve(rankedResultsCount >= this.minimumRankedResultsCount);
12
12
  }
13
13
  async forSitemapGenerator(filterKeyValues) {
14
- if (!this.rankingApiClient) {
15
- throw new DependencyMissingError('RankingApiClient');
14
+ if (!this.searchApiClient) {
15
+ throw new DependencyMissingError('SearchApiClient');
16
16
  }
17
- const rankedResultsCount = await this.rankingApiClient.getRankedOrganisationCount(filterKeyValues);
17
+ if (!this.searchApiClient.getCountWithRankings) {
18
+ const filterKeys = [...filterKeyValues.keys()];
19
+ throw new DependencyMissingError(`CountwithRankings ${filterKeys.join(',')}`);
20
+ }
21
+ const rankedResultsCount = await this.searchApiClient.getCountWithRankings(filterKeyValues);
18
22
  return rankedResultsCount >= this.minimumRankedResultsCount;
19
23
  }
20
24
  getName() {
21
- return 'AtLeastTwoRankedResultsRule';
25
+ return 'AtLeastFourRankedResultsRule';
22
26
  }
23
27
  getDescription() {
24
28
  return `At least ${this.minimumRankedResultsCount} ranked results are available`;
@@ -1,9 +1,7 @@
1
1
  import { ISitemapDependencies } from '../../common/ISitemapDependencies';
2
- import { IRankingApiClient } from '../../sitemap-generator/IRankingApiClient';
3
2
  import { PortalType } from '@studyportals/domain-client';
4
3
  import { IOrganisationsClient } from '../../sitemap-generator/IOrganisationsClient';
5
4
  export interface IOrganisationsSitemapDependencies extends ISitemapDependencies {
6
5
  organisationsClient: IOrganisationsClient;
7
6
  portalType: PortalType;
8
- rankingApiClient: IRankingApiClient;
9
7
  }
@@ -10,7 +10,7 @@ import { AttendancePresenter } from '../../presenters/AttendancePresenter';
10
10
  import { DegreePresenter } from '../../presenters/DegreePresenter';
11
11
  export class CountryAttendanceDegree extends ProgrammesBaseIndexabilityPolicy {
12
12
  name = 'Country Attendance Degree Policy';
13
- description = `Determines indexing rules for pages filtered by country,
13
+ description = `Determines indexing rules for pages filtered by country,
14
14
  study format (online, on-campus, etc.), and degree type.`;
15
15
  filterKeys = [FilterKey.COUNTRY, FilterKey.DELIVERY_METHOD, FilterKey.DEGREE_TYPE];
16
16
  rules = [
@@ -10,7 +10,7 @@ import { DegreePresenter } from '../../presenters/DegreePresenter';
10
10
  import { DurationPresenter } from '../../presenters/DurationPresenter';
11
11
  export class CountryDurationDegree extends ProgrammesBaseIndexabilityPolicy {
12
12
  name = 'Country Duration Degree Policy';
13
- description = `Determines indexing rules for pages filtered by country,
13
+ description = `Determines indexing rules for pages filtered by country,
14
14
  duration (1 year, 2 years, etc.), and degree type.`;
15
15
  filterKeys = [FilterKey.COUNTRY, FilterKey.DURATION, FilterKey.DEGREE_TYPE];
16
16
  rules = [
@@ -8,7 +8,7 @@ import { CountryPresenter } from '../../presenters/CountryPresenter';
8
8
  import { EducationalFormPresenter } from '../../presenters/EducationalFormPresenter';
9
9
  export class CountryEducationalForm extends ProgrammesBaseIndexabilityPolicy {
10
10
  name = 'Country Educational Form Policy';
11
- description = `Determines indexing rules for pages filtered by both country,
11
+ description = `Determines indexing rules for pages filtered by both country,
12
12
  and educational form (academic, semester, summer school, etc.).`;
13
13
  filterKeys = [FilterKey.COUNTRY, FilterKey.EDUCATIONAL_FORM];
14
14
  rules;
@@ -3,7 +3,7 @@ import { FilterCombinations } from '../../enums/FilterCombinations';
3
3
  import { ProgrammesBaseIndexabilityPolicy } from '../ProgrammesBaseIndexabilityPolicy';
4
4
  import { IProgrammeSeoDependencies } from '../types/IProgrammeSeoDependencies';
5
5
  import { IRule } from '../../common/IRule';
6
- export declare class DegreeAttendanceTuitionFee extends ProgrammesBaseIndexabilityPolicy {
6
+ export declare class DegreeTuitionFeeAttendance extends ProgrammesBaseIndexabilityPolicy {
7
7
  readonly name: string;
8
8
  readonly description: string;
9
9
  readonly filterKeys: FilterKey[];
@@ -10,19 +10,19 @@ import { AttendancePresenter } from '../../presenters/AttendancePresenter';
10
10
  import { OnlineAttendanceRule } from '../../common/rules/OnlineAttendanceRule';
11
11
  import { IndexableDegreeRule } from '../rules/IndexableDegreeRule';
12
12
  import { AffordableTuitionFeeRule } from '../rules/AffordableTuitionFeeRule';
13
- export class DegreeAttendanceTuitionFee extends ProgrammesBaseIndexabilityPolicy {
13
+ export class DegreeTuitionFeeAttendance extends ProgrammesBaseIndexabilityPolicy {
14
14
  name = 'Tuition Fee Attendance Degree Policy';
15
15
  description = 'Determines indexing rules for pages filtered by tuition fee, attendance, and degree type.';
16
- filterKeys = [FilterKey.TUITION_FEE, FilterKey.DELIVERY_METHOD, FilterKey.DEGREE_TYPE];
16
+ filterKeys = [FilterKey.DEGREE_TYPE, FilterKey.TUITION_FEE, FilterKey.DELIVERY_METHOD];
17
17
  rules;
18
18
  constructor(dependencies) {
19
19
  super(dependencies);
20
20
  const portalType = dependencies.portalType;
21
21
  this.rules = [
22
22
  new SingleValueSelectedForFilterRule(FilterKey.DEGREE_TYPE),
23
- new SingleValueSelectedForFilterRule(FilterKey.DELIVERY_METHOD),
24
23
  new SingleValueSelectedForFilterRule(FilterKey.TUITION_FEE),
25
- new OnlyFiltersSelectedRule([FilterKey.DEGREE_TYPE, FilterKey.DELIVERY_METHOD, FilterKey.TUITION_FEE]),
24
+ new SingleValueSelectedForFilterRule(FilterKey.DELIVERY_METHOD),
25
+ new OnlyFiltersSelectedRule([FilterKey.DEGREE_TYPE, FilterKey.TUITION_FEE, FilterKey.DELIVERY_METHOD]),
26
26
  new IndexableDegreeRule(portalType),
27
27
  new OnlineAttendanceRule(),
28
28
  new AffordableTuitionFeeRule()
@@ -42,9 +42,9 @@ export class DegreeAttendanceTuitionFee extends ProgrammesBaseIndexabilityPolicy
42
42
  for (const degree of degreeFragments) {
43
43
  for (const attendance of attendanceFragments) {
44
44
  const filterKeyValues = new Map([
45
- [FilterKey.DELIVERY_METHOD, [attendance.id]],
46
45
  [FilterKey.DEGREE_TYPE, [degree.id]],
47
- [FilterKey.TUITION_FEE, [affordableTuition.id]]
46
+ [FilterKey.TUITION_FEE, [affordableTuition.id]],
47
+ [FilterKey.DELIVERY_METHOD, [attendance.id]]
48
48
  ]);
49
49
  const result = await this.checkRulesForSitemapWithPageNumber(filterKeyValues, pageNumber);
50
50
  if (result) {
@@ -3,7 +3,7 @@ import { FilterCombinations } from '../../enums/FilterCombinations';
3
3
  import { ProgrammesBaseIndexabilityPolicy } from '../ProgrammesBaseIndexabilityPolicy';
4
4
  import { IProgrammeSeoDependencies } from '../types/IProgrammeSeoDependencies';
5
5
  import { IRule } from '../../common/IRule';
6
- export declare class DegreeContinentTuitionFee extends ProgrammesBaseIndexabilityPolicy {
6
+ export declare class DegreeTuitionFeeContinent extends ProgrammesBaseIndexabilityPolicy {
7
7
  readonly name: string;
8
8
  readonly description: string;
9
9
  readonly filterKeys: FilterKey[];
@@ -7,10 +7,10 @@ import { ProgrammesBaseIndexabilityPolicy } from '../ProgrammesBaseIndexabilityP
7
7
  import { DegreePresenter } from '../../presenters/DegreePresenter';
8
8
  import { ContinentPresenter } from '../../presenters/ContinentPresenter';
9
9
  import { TuitionFeePresenter } from '../../presenters/TuitionFeePresenter';
10
- export class DegreeContinentTuitionFee extends ProgrammesBaseIndexabilityPolicy {
11
- name = 'Degree Continent Tuition Fee Policy';
12
- description = 'Determines indexing rules for pages filtered by degree type, continent, and tuition fee.';
13
- filterKeys = [FilterKey.DEGREE_TYPE, FilterKey.CONTINENT, FilterKey.TUITION_FEE];
10
+ export class DegreeTuitionFeeContinent extends ProgrammesBaseIndexabilityPolicy {
11
+ name = 'Degree Tuition Fee Continent Policy';
12
+ description = 'Determines indexing rules for pages filtered by degree type, tuition fee, and continent.';
13
+ filterKeys = [FilterKey.DEGREE_TYPE, FilterKey.TUITION_FEE, FilterKey.CONTINENT];
14
14
  rules;
15
15
  constructor(dependencies) {
16
16
  super(dependencies);
@@ -19,7 +19,7 @@ export class DegreeContinentTuitionFee extends ProgrammesBaseIndexabilityPolicy
19
19
  new SingleValueSelectedForFilterRule(FilterKey.CONTINENT),
20
20
  new SingleValueSelectedForFilterRule(FilterKey.DEGREE_TYPE),
21
21
  new SingleValueSelectedForFilterRule(FilterKey.TUITION_FEE),
22
- new OnlyFiltersSelectedRule([FilterKey.CONTINENT, FilterKey.DEGREE_TYPE, FilterKey.TUITION_FEE]),
22
+ new OnlyFiltersSelectedRule([FilterKey.DEGREE_TYPE, FilterKey.TUITION_FEE, FilterKey.CONTINENT]),
23
23
  new IndexableDegreeRule(portalType)
24
24
  ];
25
25
  this.initateBaseRules();
@@ -34,9 +34,9 @@ export class DegreeContinentTuitionFee extends ProgrammesBaseIndexabilityPolicy
34
34
  for (const degree of degreeFragments) {
35
35
  for (const tuitionFee of tuitionFeeFragments) {
36
36
  const filterKeyValues = new Map([
37
- [FilterKey.CONTINENT, [continent.id]],
38
37
  [FilterKey.DEGREE_TYPE, [degree.id]],
39
38
  [FilterKey.TUITION_FEE, [tuitionFee.id]],
39
+ [FilterKey.CONTINENT, [continent.id]],
40
40
  ]);
41
41
  const result = await this.checkRulesForSitemapWithPageNumber(filterKeyValues, pageNumber);
42
42
  if (result) {
@@ -12,16 +12,16 @@ import { PartTimeFormatRule } from '../rules/PartTimeFormatRule';
12
12
  export class DegreeFormatTuitionFee extends ProgrammesBaseIndexabilityPolicy {
13
13
  name = 'Degree Format Tuition Fee Policy';
14
14
  description = 'Determines indexing rules for pages filtered by degree type, format and tuition fee.';
15
- filterKeys = [FilterKey.DEGREE_TYPE, FilterKey.ATTENDANCE, FilterKey.TUITION_FEE];
15
+ filterKeys = [FilterKey.DEGREE_TYPE, FilterKey.TUITION_FEE, FilterKey.ATTENDANCE];
16
16
  rules;
17
17
  constructor(dependencies) {
18
18
  super(dependencies);
19
19
  const portalType = dependencies.portalType;
20
20
  this.rules = [
21
- new SingleValueSelectedForFilterRule(FilterKey.ATTENDANCE),
22
21
  new SingleValueSelectedForFilterRule(FilterKey.DEGREE_TYPE),
23
22
  new SingleValueSelectedForFilterRule(FilterKey.TUITION_FEE),
24
- new OnlyFiltersSelectedRule([FilterKey.ATTENDANCE, FilterKey.DEGREE_TYPE, FilterKey.TUITION_FEE]),
23
+ new SingleValueSelectedForFilterRule(FilterKey.ATTENDANCE),
24
+ new OnlyFiltersSelectedRule([FilterKey.DEGREE_TYPE, FilterKey.TUITION_FEE, FilterKey.ATTENDANCE]),
25
25
  new IndexableDegreeRule(portalType),
26
26
  new AffordableTuitionFeeRule(),
27
27
  new PartTimeFormatRule()
@@ -38,9 +38,9 @@ export class DegreeFormatTuitionFee extends ProgrammesBaseIndexabilityPolicy {
38
38
  for (const degree of degreeFragments) {
39
39
  for (const tuitionFee of tuitionFeeFragments) {
40
40
  const filterKeyValues = new Map([
41
- [FilterKey.ATTENDANCE, [format.id]],
42
41
  [FilterKey.DEGREE_TYPE, [degree.id]],
43
- [FilterKey.TUITION_FEE, [tuitionFee.id]]
42
+ [FilterKey.TUITION_FEE, [tuitionFee.id]],
43
+ [FilterKey.ATTENDANCE, [format.id]],
44
44
  ]);
45
45
  const result = await this.checkRulesForSitemapWithPageNumber(filterKeyValues, pageNumber);
46
46
  if (result) {
@@ -9,7 +9,7 @@ import { CountryPresenter } from '../../presenters/CountryPresenter';
9
9
  import { EducationalFormPresenter } from '../../presenters/EducationalFormPresenter';
10
10
  export class DisciplineCountryEducationalForm extends ProgrammesBaseIndexabilityPolicy {
11
11
  name = 'Discipline Country Educational Form Policy';
12
- description = `Determines indexing rules for pages filtered by discipline,
12
+ description = `Determines indexing rules for pages filtered by discipline,
13
13
  country, and educational form (academic, semester, summer school, etc.).`;
14
14
  filterKeys = [FilterKey.DISCIPLINES, FilterKey.COUNTRY, FilterKey.EDUCATIONAL_FORM];
15
15
  rules;
@@ -8,7 +8,7 @@ import { DisciplinePresenter } from '../../presenters/DisciplinePresenter';
8
8
  import { EducationalFormPresenter } from '../../presenters/EducationalFormPresenter';
9
9
  export class DisciplineEducationalForm extends ProgrammesBaseIndexabilityPolicy {
10
10
  name = 'Discipline Educational Form Policy';
11
- description = `Determines indexing rules for pages filtered by both discipline,
11
+ description = `Determines indexing rules for pages filtered by both discipline,
12
12
  and educational form (academic, semester, summer school, etc.).`;
13
13
  filterKeys = [FilterKey.DISCIPLINES, FilterKey.EDUCATIONAL_FORM];
14
14
  rules;
@@ -11,4 +11,5 @@ export interface ISearchApiClient {
11
11
  }[]>;
12
12
  getProgrammeCount?(filterKeyValues: FilterKeyValuesMap): Promise<number>;
13
13
  getCount(filterKeyValues: FilterKeyValuesMap): Promise<number>;
14
+ getCountWithRankings?(filterKeyValues: FilterKeyValuesMap): Promise<number>;
14
15
  }
@@ -3,12 +3,11 @@ import { IOrganisationsClient } from '../sitemap-generator/IOrganisationsClient'
3
3
  import { ISearchApiClient } from '../sitemap-generator/ISearchApiClient';
4
4
  import { BaseSitemapUrlGeneratorManager } from './BaseSitemapUrlGeneratorManager';
5
5
  import { PortalType } from '@studyportals/domain-client';
6
- import { IRankingApiClient } from './IRankingApiClient';
7
6
  import { FilterKey } from '@studyportals/search-filters/server-side';
8
7
  import { IPresenter } from '../common';
9
8
  export declare class OrganisationsSitemapUrlGeneratorManager extends BaseSitemapUrlGeneratorManager {
10
9
  readonly portalType: PortalType;
11
10
  readonly policies: ISitemapUrlGenerator[];
12
11
  readonly presenters: Map<FilterKey, IPresenter>;
13
- constructor(portalType: PortalType, searchApiClient: ISearchApiClient, organisationsClient: IOrganisationsClient, rankingApiClient: IRankingApiClient);
12
+ constructor(portalType: PortalType, searchApiClient: ISearchApiClient, organisationsClient: IOrganisationsClient);
14
13
  }
@@ -1,6 +1,6 @@
1
1
  import { DependencyTypes } from '../enums/DependencyTypes';
2
2
  import { BaseSitemapUrlGeneratorManager } from './BaseSitemapUrlGeneratorManager';
3
- import { Area, AreaAttendance, Attendance, Continent, Country, CountryCity, CountryAttendance, RankedArea, RankedAreaDiscipline, RankedAttendance, RankedAttendanceDiscipline, RankedContinent, RankedContinentAttendance, RankedCountry, RankedCountryAttendance, RankedCountryDiscipline, RankedDiscipline, RankedUnfiltered, Unfiltered } from '../organisations/policies';
3
+ import { Area, AreaAttendance, Attendance, Continent, Country, CountryCity, CountryAttendance, RankedArea, RankedAttendance, RankedAttendanceDiscipline, RankedContinent, RankedContinentAttendance, RankedCountry, RankedCountryAttendance, RankedCountryDiscipline, RankedDiscipline, RankedUnfiltered, Unfiltered } from '../organisations/policies';
4
4
  import { AreaPresenter } from '../presenters/AreaPresenter';
5
5
  import { AttendancePresenter } from '../presenters/AttendancePresenter';
6
6
  import { ContinentPresenter } from '../presenters/ContinentPresenter';
@@ -12,7 +12,7 @@ export class OrganisationsSitemapUrlGeneratorManager extends BaseSitemapUrlGener
12
12
  portalType;
13
13
  policies;
14
14
  presenters = new Map();
15
- constructor(portalType, searchApiClient, organisationsClient, rankingApiClient) {
15
+ constructor(portalType, searchApiClient, organisationsClient) {
16
16
  super();
17
17
  this.portalType = portalType;
18
18
  const dependencies = {
@@ -20,7 +20,6 @@ export class OrganisationsSitemapUrlGeneratorManager extends BaseSitemapUrlGener
20
20
  portalType,
21
21
  searchApiClient,
22
22
  organisationsClient,
23
- rankingApiClient
24
23
  };
25
24
  this.policies = [
26
25
  new CountryCity(dependencies),
@@ -33,7 +32,6 @@ export class OrganisationsSitemapUrlGeneratorManager extends BaseSitemapUrlGener
33
32
  new CountryAttendance(dependencies),
34
33
  new Unfiltered(dependencies),
35
34
  new RankedArea(dependencies),
36
- new RankedAreaDiscipline(dependencies),
37
35
  new RankedAttendance(dependencies),
38
36
  new RankedAttendanceDiscipline(dependencies),
39
37
  new RankedContinent(dependencies),
package/package.json CHANGED
@@ -1,105 +1,106 @@
1
- {
2
- "name": "@studyportals/fawkes",
3
- "version": "8.7.2",
4
- "description": "A package to centralize SEO related logic for SBLP and Sitemap Generator.",
5
- "files": [
6
- "./dist"
7
- ],
8
- "scripts": {
9
- "prepush": "npm run test",
10
- "precommit": "npm run lint",
11
- "compile": "npx tsc && tsc-alias && rm -r ./dist/tests",
12
- "build": "npm run clean && npm run compile",
13
- "clean": "rimraf \"!(node_modules)/**/dist\"",
14
- "prepare-deployment": "npm run test && npm run build",
15
- "publish-major": "npm run prepare-deployment && npm version major && npm publish",
16
- "publish-beta": "npm run prepare-deployment && npm version prerelease && npm publish --tag beta --access=public",
17
- "publish-patch": "npm run prepare-deployment && npm version patch && npm publish",
18
- "publish-minor": "npm run prepare-deployment && npm version minor && npm publish",
19
- "prepare": "husky install",
20
- "test": "vitest run --coverage",
21
- "test:dev": "vitest --coverage tests/programmes",
22
- "lint": "eslint . --ext .ts",
23
- "lint:fix": "eslint . --ext .ts --fix",
24
- "prettier:fix": "npx prettier --use-tabs --ignore-path .gitignore --write ."
25
- },
26
- "exports": {
27
- "./organisations-search-seo": {
28
- "import": "./dist/organisations-seo/index.js",
29
- "require": "./dist/organisations-seo/index.js",
30
- "types": "./dist/organisations-seo/index.d.ts"
31
- },
32
- "./programmes-search-seo": {
33
- "import": "./dist/programmes-seo/index.js",
34
- "require": "./dist/programmes-seo/index.js",
35
- "types": "./dist/programmes-seo/index.d.ts"
36
- },
37
- "./scholarships-search-seo": {
38
- "import": "./dist/scholarships-seo/index.js",
39
- "require": "./dist/scholarships-seo/index.js",
40
- "types": "./dist/scholarships-seo/index.d.ts"
41
- },
42
- "./sitemap-generator-seo": {
43
- "import": "./dist/sitemap-generator-seo/index.js",
44
- "require": "./dist/sitemap-generator-seo/index.js",
45
- "types": "./dist/sitemap-generator-seo/index.d.ts"
46
- },
47
- "./structured-data-seo": {
48
- "import": "./dist/structured-data-seo/index.js",
49
- "require": "./dist/structured-data-seo/index.js",
50
- "types": "./dist/structured-data-seo/index.d.ts"
51
- }
52
- },
53
- "typesVersions": {
54
- "*": {
55
- "organisations-search-seo": [
56
- "dist/organisations-seo/index.d.ts"
57
- ],
58
- "programmes-search-seo": [
59
- "dist/programmes-seo/index.d.ts"
60
- ],
61
- "scholarships-search-seo": [
62
- "dist/scholarships-seo/index.d.ts"
63
- ],
64
- "sitemap-generator-seo": [
65
- "dist/sitemap-generator-seo/index.d.ts"
66
- ],
67
- "structured-data-seo": [
68
- "dist/structured-data-seo/index.d.ts"
69
- ],
70
- "*": [
71
- "dist/index.d.ts"
72
- ]
73
- }
74
- },
75
- "author": "The Jedi Council",
76
- "license": "ISC",
77
- "devDependencies": {
78
- "@adobe/structured-data-validator": "^1.4.1",
79
- "@studyportals/code-style": "^2.2.1",
80
- "@studyportals/webpack-helper": "^6.0.6",
81
- "@vitest/coverage-istanbul": "^2.1.8",
82
- "husky": "^8.0.3",
83
- "jsdom": "^26.0.0",
84
- "prettier": "^3.5.3",
85
- "schema-dts": "^1.1.5",
86
- "ts-loader": "^9.5.2",
87
- "tsc-alias": "^1.8.11",
88
- "typemoq": "^2.1.0",
89
- "typescript": "^5.7.3",
90
- "vitest": "^2.1.8"
91
- },
92
- "dependencies": {
93
- "@studyportals/domain-client": "^8.2.0",
94
- "@studyportals/ranking-api-interface": "^1.3.12",
95
- "@studyportals/search-filters": "^6.3.1",
96
- "@studyportals/static-domain-data": "^6.1.0"
97
- },
98
- "optionalDependencies": {
99
- "@rollup/rollup-linux-x64-gnu": "4.24.0"
100
- },
101
- "engines": {
102
- "node": ">=18 <=24",
103
- "npm": ">=8 <=11"
104
- }
105
- }
1
+ {
2
+ "name": "@studyportals/fawkes",
3
+ "version": "9.0.0",
4
+ "description": "A package to centralize SEO related logic for SBLP and Sitemap Generator.",
5
+ "files": [
6
+ "./dist"
7
+ ],
8
+ "scripts": {
9
+ "prepush": "npm run test",
10
+ "precommit": "npm run lint",
11
+ "compile": "npx tsc && tsc-alias && rm -r ./dist/tests",
12
+ "build": "npm run clean && npm run compile",
13
+ "clean": "rimraf \"!(node_modules)/**/dist\"",
14
+ "prepare-deployment": "npm run test && npm run build",
15
+ "publish-major": "npm run prepare-deployment && npm version major && npm publish",
16
+ "publish-beta": "npm run prepare-deployment && npm version prerelease && npm publish --tag beta --access=public",
17
+ "publish-patch": "npm run prepare-deployment && npm version patch && npm publish",
18
+ "publish-minor": "npm run prepare-deployment && npm version minor && npm publish",
19
+ "prepare": "husky install",
20
+ "test": "vitest run --coverage",
21
+ "test:dev": "vitest --coverage tests/programmes",
22
+ "lint": "eslint . --ext .ts",
23
+ "lint:fix": "eslint . --ext .ts --fix",
24
+ "prettier:fix": "npx prettier --use-tabs --ignore-path .gitignore --write ."
25
+ },
26
+ "exports": {
27
+ "./organisations-search-seo": {
28
+ "import": "./dist/organisations-seo/index.js",
29
+ "require": "./dist/organisations-seo/index.js",
30
+ "types": "./dist/organisations-seo/index.d.ts"
31
+ },
32
+ "./programmes-search-seo": {
33
+ "import": "./dist/programmes-seo/index.js",
34
+ "require": "./dist/programmes-seo/index.js",
35
+ "types": "./dist/programmes-seo/index.d.ts"
36
+ },
37
+ "./scholarships-search-seo": {
38
+ "import": "./dist/scholarships-seo/index.js",
39
+ "require": "./dist/scholarships-seo/index.js",
40
+ "types": "./dist/scholarships-seo/index.d.ts"
41
+ },
42
+ "./sitemap-generator-seo": {
43
+ "import": "./dist/sitemap-generator-seo/index.js",
44
+ "require": "./dist/sitemap-generator-seo/index.js",
45
+ "types": "./dist/sitemap-generator-seo/index.d.ts"
46
+ },
47
+ "./structured-data-seo": {
48
+ "import": "./dist/structured-data-seo/index.js",
49
+ "require": "./dist/structured-data-seo/index.js",
50
+ "types": "./dist/structured-data-seo/index.d.ts"
51
+ }
52
+ },
53
+ "typesVersions": {
54
+ "*": {
55
+ "organisations-search-seo": [
56
+ "dist/organisations-seo/index.d.ts"
57
+ ],
58
+ "programmes-search-seo": [
59
+ "dist/programmes-seo/index.d.ts"
60
+ ],
61
+ "scholarships-search-seo": [
62
+ "dist/scholarships-seo/index.d.ts"
63
+ ],
64
+ "sitemap-generator-seo": [
65
+ "dist/sitemap-generator-seo/index.d.ts"
66
+ ],
67
+ "structured-data-seo": [
68
+ "dist/structured-data-seo/index.d.ts"
69
+ ],
70
+ "*": [
71
+ "dist/index.d.ts"
72
+ ]
73
+ }
74
+ },
75
+ "author": "The Jedi Council",
76
+ "license": "ISC",
77
+ "devDependencies": {
78
+ "@adobe/structured-data-validator": "^1.4.1",
79
+ "@studyportals/code-style": "^2.2.1",
80
+ "@studyportals/webpack-helper": "^6.0.6",
81
+ "@vitest/coverage-istanbul": "^2.1.8",
82
+ "husky": "^8.0.3",
83
+ "jsdom": "^26.0.0",
84
+ "prettier": "^3.5.3",
85
+ "schema-dts": "^1.1.5",
86
+ "ts-loader": "^9.5.2",
87
+ "tsc-alias": "^1.8.11",
88
+ "typemoq": "^2.1.0",
89
+ "typescript": "^5.7.3",
90
+ "vitest": "^2.1.8"
91
+ },
92
+ "dependencies": {
93
+ "@studyportals/domain-client": "^8.1.0",
94
+ "@studyportals/ranking-api-interface": "^2.4.0",
95
+ "@studyportals/search-api-interface": "5.9.3-0",
96
+ "@studyportals/search-filters": "^6.3.1",
97
+ "@studyportals/static-domain-data": "^6.1.0"
98
+ },
99
+ "optionalDependencies": {
100
+ "@rollup/rollup-linux-x64-gnu": "4.24.0"
101
+ },
102
+ "engines": {
103
+ "node": ">=18 <=24",
104
+ "npm": ">=8 <=11"
105
+ }
106
+ }