Skip to content

feat: snapshot every plugin API sub-path - #645

Merged
guimard merged 1 commit into
v3.0from
refactor/595-plugin-api-reports
Nov 2, 2026
Merged

guimard merged 1 commit into
v3.0from
refactor/595-plugin-api-reports

Conversation

@guimard

@guimard guimard commented Nov 2, 2026

Copy link
Copy Markdown
Member

Part of #595.

The etc/api/ reports only covered the five main entry points, so a change to a ./plugin-* type was still reviewed by hand. This adds one report per plugin sub-path.

Reports

  • API_ENTRIES now reads the ./plugin-* entries from package.json exports, so a new plugin is reported without another list to update.
  • 88 plugin reports are committed under etc/api/, next to the five main ones (93 total).
  • npm run check:api regenerates and compares them; it takes about 35 seconds on this tree.

The contracts gate already compares every listed report with the base, so a removed plugin declaration is non-additive there, and a changed one is printed for review. The limitation on telling an added optional member from a narrowed union is unchanged and still documented.

docs/development/contracts.md describes the plugin reports and drops the “66 plugin entries come later” note.

Verification: npm run check passes; test/scripts/apiSnapshot.test.ts passes (9 tests).

Refs #595.

@guimard
guimard requested a review from rezk2ll as a code owner November 2, 2026 21:12
@guimard

guimard commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

Review of 5464577.

Mechanics are right. All 88 ./plugin-* exports carry types, and the slice(2).replace('/', '-') names don't collide, so Object.fromEntries drops nothing. An orphan report fails check:api. A plugin removed from exports is still caught by contracts, because it also lists the base's etc/api/.

Blocking (to decide): each plugin report repeats the core surface. etc/api/ goes from 5 files / 186 KiB to 93 files / 3.2 MiB. Splitting the reports into declaration blocks shows that 94 % of the plugin report lines (96,884 of 103,341) are blocks identical to one in the five core reports. includeForgottenExports inlines Config (569 lines), DM, DmPlugin, ldapActions… into each plugin's report. interface Config appears in 76 of the 88 plugin reports.

What follows from that:

  • Adding a CLI option to Config (src/config/args.ts has 46 commits since October) rewrites about 80 reports. Two PRs that each add an option conflict in about 80 files, and the fix is a regeneration.
  • The contracts gate prints ~ changed <entry> declaration Config once per report, about 80 lines. The plugin's own changes get lost in them, and those are what this PR is meant to show.
  • The core reports already gate these declarations, so the plugin reports add no coverage on them.

#595 called this "a dependency and repository-size decision of its own". The PR body doesn't mention the size.

A suggestion: post-process each plugin report so it drops the declaration blocks identical to a block in a core report generated in the same run. A core change then moves the core report only, and both copies of an inlined type stay equal. A plugin type that shares a core name but has a different shape is kept. diffApiReports does not change. The reports would come down to about 6,500 lines in total.

Nits:

  • docs/development/contracts.md: "…needs more than a line diff. Renaming an option is a deprecation…" is a line past the wrap width, because the paragraph wasn't rewrapped after the deletion.
  • scripts/api-snapshot.ts: the orphan message still says "list its entry in API_ENTRIES". For a plugin, the entry now comes from package.json exports.

@guimard
guimard force-pushed the refactor/595-plugin-api-reports branch from 5464577 to c5405a6 Compare November 2, 2026 21:18
@guimard

guimard commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

Le point bloquant est traité dans c5405a68 : la revue avait raison, les rapports plugin répétaient la surface du core.

Déduplication
Chaque rapport plugin supprime maintenant les blocs de déclaration identiques à un bloc d’un des cinq rapports core produits dans le même run. Un Config, DM, DmPlugin ou ldapActions inline n’apparaît plus que dans le rapport core ; un type plugin qui partage un nom avec un type core mais a une forme différente est conservé. diffApiReports n’a pas changé.

Résultat :

  • etc/api/ passe de 3,2 MiB / 103 341 lignes à 632 KiB / 14 210 lignes ;
  • plugin-auth-authzlinid1.api.md fait 107 lignes ;
  • interface Config n’apparaît plus que dans ldap-rest.api.md (et ConfigApiResponse local du plugin configApi, qui est un autre type).

Une modification de Config ne réécrit donc plus 80 rapports, et le gate contracts ne répète plus ~ changed <entry> declaration Config pour chaque plugin.

Nits

  • Le paragraphe de docs/development/contracts.md est réenroulé, et il explique la déduplication.
  • Le message de rapport orphelin parle maintenant de package.json exports, plus de API_ENTRIES.

npm run check passe, check:api passe (environ 34 s) et test/scripts/apiSnapshot.test.ts passe.

@guimard

guimard commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

Re-review of c5405a6: the blocking point is fixed. check:api passes on the branch (the regenerated reports match the committed ones), apiSnapshot.test.ts passes, and Prettier is clean. No plugin report carries interface Config any more. Small correction to the comment above: it still sits in plugin.api.md, ldapactions.api.md and hooks.api.md, not in ldap-rest.api.md.

Two non-blocking points:

  1. check:api now warns on every plugin report. buildApiReports seeds the folder with the committed reports, which are now stripped. API Extractor then compares its full report with them and prints Warning: You have changed the API signature for this project. Updating temp/api/check/plugin-….api.md. On this branch, with no change, a check:api run prints it 85 times, all for plugin-* reports and none for a core one. A real signature warning would be buried in them. Either skip the seed for the plugin entries, or handle those messages in ignoreNoise (ae- messages for a report that is stripped afterwards). The stale check compares the stripped files anyway.

  2. No unit test for stripCoreDeclarations. Two cases next to the diffApiReports tests in test/scripts/apiSnapshot.test.ts would pin it: a block identical to a core one is dropped, and a declaration sharing a core name with a different shape is kept. The header and closing fence should come out untouched.

`etc/api/` only pinned the five main entry points, so a change to a
`./plugin-*` type was still reviewed by hand. The entries now come from
`package.json` exports, and the reports for every plugin are committed.

Each plugin report drops the declaration blocks it shares verbatim with a
core report: the core report already gates those, and repeating them would
rewrite every plugin report on a core option change. The 88 plugin reports
take 632 KiB in total instead of 3.2 MiB. API Extractor's report-copied and
report-created warnings are ignored, since the stale check compares the
stripped files themselves.

Two tests pin the stripping: an identical block goes, another shape of a
core name stays.

Refs #595.
@guimard
guimard force-pushed the refactor/595-plugin-api-reports branch from c5405a6 to e117dc5 Compare November 2, 2026 21:24
@guimard

guimard commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

Les deux points sont corrigés dans e117dc5b.

1. Plus d’avertissements à chaque rapport plugin. ignoreNoise traite maintenant console-api-report-copied et console-api-report-created : les rapports seedés sont complets, l’extraction les compare, puis nous les dédupliquons, donc le « changed API signature » n’a plus de sens à ce stade. La vérification de fraîcheur compare bien les fichiers dédupliqués. npm run check:api ne produit plus aucun de ces avertissements (0 sur ce run) et passe.

2. Tests de stripCoreDeclarations. test/scripts/apiSnapshot.test.ts a deux cas :

  • un bloc identique à un bloc core est supprimé, l’en-tête et la clôture restent intacts ;
  • une déclaration de même nom (Config) mais de forme différente est conservée.

npm run check passe et apiSnapshot.test.ts compte 11 tests.

@guimard

guimard commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

Re-review of e117dc5: verified, nothing left to change.

  1. The two IDs ignoreNoise now handles are the ones API Extractor logs these messages under (ConsoleMessageId.ApiReportCopied for "You have changed the API signature…" and ApiReportCreated for "The API report file was missing…"). The stale check still compares the stripped files, so a real change is still caught.
  2. The two stripCoreDeclarations cases pin what they should: an identical block is dropped, with the header and closing fence intact, and a same-name Config with another shape is kept.

Note, no change needed: the filter applies to the core reports too, so npm run snapshot:api no longer announces a core signature change either. Nothing is lost: check:api still reports the core file as stale, and contracts prints the diff.

@guimard
guimard merged commit b4f279f into v3.0 Nov 2, 2026
7 checks passed
@guimard
guimard deleted the refactor/595-plugin-api-reports branch November 2, 2026 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant