PhoenixKitProjects.Extensions.Registry (PhoenixKitProjects v0.21.1)

Copy Markdown View Source

Discovers and caches the project-extension catalog.

The catalog is the union of every PhoenixKit module defining phoenix_kit_project_extensions/0 (see PhoenixKitProjects.Extensions.Extension for the contract). This module's own PhoenixKitProjects is one such provider — the built-in Tasks extension and the hub-side bridge descriptors (for modules that don't self-declare, e.g. comments) ship through the same entry point, no special-cased path.

Host apps contribute providers without being PhoenixKit modules:

config :phoenix_kit_projects, extension_providers: [MyApp.ProjectExtensions]

The catalog structure is memoized in :persistent_term (the dashboards Registry pattern). Module enablement and permission are re-checked live on every read; a newly installed provider or changed descriptor needs refresh/0 (this module calls it on its own enable).

Summary

Functions

Whether the extension's backing site module (if any) is enabled.

The full extension catalog, keyed by extension key. Memoized.

Category keys with display labels, in scan order.

The category an extension belongs to: its declared category when it names a known one, else the built-in fallback for its key, else "more".

Look up one extension type by key.

Extensions grouped for display: [{category_key, label, [extension]}], in scan order, with empty categories dropped.

All catalog extensions, stable order (built-ins first, then by name).

Catalog extensions OFFERABLE right now: the backing site module (if any) is enabled. This is the availability half of the gate; per-scope permission is checked separately via visible_for_scope?/2 because the Modules panel wants to show unavailable extensions greyed-out rather than hidden.

Rebuild the catalog from every discovered provider and re-cache it.

Whether a scope may SEE this extension's contributed surface. The required permission resolves permissionmodule_key → the hub's own "projects" — so a tab re-exporting a SIBLING module's data (CRM/entities/publishing) requires that module's permission, exactly what the descriptor comments promise, while hub-owned built-ins ride the projects permission the viewer already holds (final panel, Grok: the gate existed but nothing consulted module_key, so any projects viewer could read linked sibling data through a tab). Fail-closed on a nil scope.

Functions

available?(extension)

Whether the extension's backing site module (if any) is enabled.

catalog()

@spec catalog() :: %{
  required(String.t()) => PhoenixKitProjects.Extensions.Extension.t()
}

The full extension catalog, keyed by extension key. Memoized.

categories()

@spec categories() :: [{String.t(), String.t()}]

Category keys with display labels, in scan order.

category_of(extension)

The category an extension belongs to: its declared category when it names a known one, else the built-in fallback for its key, else "more".

get(key)

Look up one extension type by key.

group_by_category(extensions)

Extensions grouped for display: [{category_key, label, [extension]}], in scan order, with empty categories dropped.

list()

All catalog extensions, stable order (built-ins first, then by name).

list_available()

@spec list_available() :: [PhoenixKitProjects.Extensions.Extension.t()]

Catalog extensions OFFERABLE right now: the backing site module (if any) is enabled. This is the availability half of the gate; per-scope permission is checked separately via visible_for_scope?/2 because the Modules panel wants to show unavailable extensions greyed-out rather than hidden.

refresh()

@spec refresh() :: %{
  required(String.t()) => PhoenixKitProjects.Extensions.Extension.t()
}

Rebuild the catalog from every discovered provider and re-cache it.

visible_for_scope?(ext, scope)

Whether a scope may SEE this extension's contributed surface. The required permission resolves permissionmodule_key → the hub's own "projects" — so a tab re-exporting a SIBLING module's data (CRM/entities/publishing) requires that module's permission, exactly what the descriptor comments promise, while hub-owned built-ins ride the projects permission the viewer already holds (final panel, Grok: the gate existed but nothing consulted module_key, so any projects viewer could read linked sibling data through a tab). Fail-closed on a nil scope.