Investigate use of Project Browser to include drupal.org info

Introduction

I had been investigating External Entities as a way to reference modules and issues on Drupal.org.

Since then, Project Browser has come around, and started using a JSONAPI endpoint.

Prior to that, drupal.org only had some custom rest APIs for sourcing content.

https://www.drupal.org/drupalorg/docs/apis/rest-and-other-apis

Routes

Browser list
/admin/modules/browse

Individual projects
/admin/modules/browse/drupalorg_jsonapi/drupal-token-token

Module categories
/drupal-org-proxy/categories

All projects
/drupal-org-proxy/project

Questions

When is data fetched from drupal.org? Is it cached?

What is an Activator? (/src/Activator.php).

What is an Enhancer? (/src/Routing/ProjectEnhancer.php)

Notes

I don't see a db schema or entity, so I don't think it stores any data?

Instructions for creating your own plugin in /modules/project_browser_source_example.

Contains sveltejs code.

BrowserController has one function, browse(), which simply renders the ProjectBrowser render element, passing in $source and $id.

Experiment

Create a controller that loads ProjectBrowserSourceManager and displays fetched module info.

*Use drush gen controller to generate a module and controller.

external_entities_drupalorg.routing.yml

external_entities_drupalorg.modules:
  path: '/drupalorg-modules'
  defaults:
    _title: 'Drupal.org Modules'
    _controller: '\Drupal\external_entities_drupalorg\Controller\ExternalEntitiesDrupalorgController'
  requirements:
    _permission: 'access content'

ExternalEntitiesDrupalorgController.php

<?php

declare(strict_types=1);

namespace Drupal\external_entities_drupalorg\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\project_browser\Plugin\ProjectBrowserSourceManager;

/**
 * Returns responses for external_entities_drupalorg routes.
 */
final class ExternalEntitiesDrupalorgController extends ControllerBase {
  public function __construct(
    private readonly ProjectBrowserSourceManager $projectBrowserSourceManager,
  ) {}

  /**
   * Builds the response.
   */public function __invoke(): array {
    /* @var \Drupal\project_browser\Plugin\ProjectBrowserSource\DrupalDotOrgJsonApi $drupalorg */
    $drupalorg = $this->projectBrowserSourceManager->createInstance('drupalorg_jsonapi');

    $build['total_results'] = [
      '#type' => 'item',
      '#markup' => $this->t('total results: ' . $drupalorg->getProjects()->totalResults),
    ];

    $pages = [0, 1];
    foreach ($pages as $page) {
      $build["page_$page"] = [
        '#type' => 'item',
        '#markup' => $this->t("Page $page"),
        '#prefix' => '<h2>',
        '#suffix' => '</h2>',
      ];

      $modules = $drupalorg->getProjects(['page' => $page])->list;

      foreach ($modules as $id => $module) {
        $build[$page][$id] = [
          '#type' => 'item',
          '#markup' => $this->t($module->title),
        ];
      }
    }

    return $build;
  }
}
Modules