Skip to content

refactor!: singularize plural enum names and fold enum extensions in - #1654

Merged
spydon merged 2 commits into
mainfrom
v3/singularize-enum-names
Aug 6, 2026
Merged

refactor!: singularize plural enum names and fold enum extensions in#1654
spydon merged 2 commits into
mainfrom
v3/singularize-enum-names

Conversation

@spydon

@spydon spydon commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Closes #1652

What

A Dart enum type names one value rather than the set, so its name should be singular. Five enums were ports of realtime-js / gotrue-js names instead:

Before After Was reachable by consumers?
ChannelStates ChannelState No (omitted from the show list)
ChannelEvents ChannelEvent No (omitted from the show list)
RealtimeListenTypes RealtimeListenType No (named in the hide clause)
PostgresTypes PostgresType Yes
AuthenticatorAssuranceLevels AuthenticatorAssuranceLevel Yes

The three unreachable ones are now annotated @internal, which is both the accurate annotation and enough to keep them out of the capability matrix scan.

Sweeping the rest of the monorepo's 51 enums turned up one more name that did not read as a noun naming a single value: LoadTableSnapshots (storage, Iceberg) is now TableSnapshotScope.

Enum extensions folded in

Enums can declare methods and static methods directly, so every extension that only existed to hang helpers off an enum is now part of the enum:

  • ChannelEventsExtendedChannelEvent.fromType / ChannelEvent.eventName
  • ToTypeRealtimeListenType.toType
  • PostgresChangeEventMethodsPostgresChangeEvent.fromString / PostgresChangeEvent.toRealtimeEvent
  • PresenceEventExtendedPresenceEvent.fromString
  • AuthChangeEventExtendedAuthChangeEvent.fromString
  • GenerateLinkTypeExtendedGenerateLinkType.fromString

Those helpers decode wire values, so the folded members carry @internal, matching the visibility the extensions already had through the hide clauses. The now-unnecessary hide entries are dropped from the gotrue and realtime_client exports.

SupabaseEventTypesName is deliberately left alone: its member is name(), which would shadow Enum.name if declared on the enum, and both it and its deprecated enum are due for removal anyway.

Not changed

Behaviour

None. No enum value changes: ChannelEvent.eventName() still produces the same phx_* strings and TableSnapshotScope still sends all / refs.

Capability matrix

PostgresType, AuthenticatorAssuranceLevel and TableSnapshotScope are registered under realtime.subscriptions.postgres_changes, auth.mfa.get_authenticator_assurance_level and storage.analytics.iceberg_table (replacing the stale LoadTableSnapshots entries).

Testing

  • dart analyze packages examples: clean
  • realtime_client, supabase, supabase_flutter suites: pass
  • gotrue MFA, constants and types suites: pass (the rest of the gotrue suite has pre-existing failures against my local stack on main too)
  • supabase/sdk check-api-symbols, check-drift and validate-compliance run locally against this branch: all pass

Summary by CodeRabbit

  • Breaking Changes

    • Renamed authentication assurance-level, realtime channel/event, Postgres type, and table snapshot enums.
    • Updated related method parameters and response fields to use the new names.
  • Improvements

    • Simplified enum parsing and conversion APIs.
    • Corrected public exports for supported types and utilities.
    • Preserved existing authentication, MFA, realtime, storage, and data-conversion behavior.
  • Tests

    • Updated coverage for enum parsing, serialization, realtime events, and MFA flows.

A Dart enum type names one value rather than the set, so its name should be
singular. Five enums were ports of realtime-js / gotrue-js names instead:

- `ChannelStates` -> `ChannelState`
- `ChannelEvents` -> `ChannelEvent`
- `RealtimeListenTypes` -> `RealtimeListenType`
- `PostgresTypes` -> `PostgresType`
- `AuthenticatorAssuranceLevels` -> `AuthenticatorAssuranceLevel`

The first three were already unreachable for consumers (omitted from the
`show` list or named in the `hide` clause of the realtime_client exports), so
they are now also annotated `@internal`, which is both accurate and keeps them
out of the capability matrix scan.

While sweeping the remaining enums, `LoadTableSnapshots` was the only other
name that did not read as a noun naming one value; it is now
`TableSnapshotScope`.

Enums can declare methods and static methods directly, so every extension that
only existed to hang helpers off an enum is folded into the enum itself:

- `ChannelEventsExtended` -> `ChannelEvent.fromType` / `ChannelEvent.eventName`
- `ToType` -> `RealtimeListenType.toType`
- `PostgresChangeEventMethods` -> `PostgresChangeEvent.fromString` / `toRealtimeEvent`
- `PresenceEventExtended` -> `PresenceEvent.fromString`
- `AuthChangeEventExtended` -> `AuthChangeEvent.fromString`
- `GenerateLinkTypeExtended` -> `GenerateLinkType.fromString`

Those helpers decode wire values, so the folded members are annotated
`@internal`, matching the visibility the extensions had via the `hide` clauses.
The now-empty `hide` entries are dropped from the gotrue and realtime_client
exports. `SupabaseEventTypesName` is left alone: its member is `name()`, which
would shadow `Enum.name` if declared on the enum, and both it and its
deprecated enum are due for removal anyway.

No enum values change and no behaviour changes: `ChannelEvent.eventName()`
still produces the same `phx_*` wire strings, and `TableSnapshotScope` still
sends `all` / `refs`.

`SocketStates` is left alone here because #1404 already renames it.

BREAKING CHANGE: `PostgresTypes` is now `PostgresType`,
`AuthenticatorAssuranceLevels` is now `AuthenticatorAssuranceLevel` and
`LoadTableSnapshots` is now `TableSnapshotScope`. The `PresenceEventExtended`
extension is gone; `PresenceEvent.fromString` replaces it and is now internal.

Closes #1652
@spydon
spydon requested a review from a team as a code owner August 5, 2026 15:35
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 18e211c3-0ec3-4444-a027-36f989850073

📥 Commits

Reviewing files that changed from the base of the PR and between 48b9387 and 4eb38c9.

📒 Files selected for processing (2)
  • packages/gotrue/lib/src/types/mfa.dart
  • packages/realtime_client/lib/src/types.dart
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/gotrue/lib/src/types/mfa.dart
  • packages/realtime_client/lib/src/types.dart

📝 Walkthrough

Walkthrough

The PR singularizes enum names across Gotrue, Realtime, and Storage. It moves conversion helpers into enum declarations, marks internal enums, updates call sites and tests, and synchronizes SDK compliance symbols.

Changes

Enum API updates

Layer / File(s) Summary
Gotrue enum and MFA contracts
packages/gotrue/lib/..., packages/gotrue/test/...
Gotrue moves parsing helpers into enum methods and renames AuthenticatorAssuranceLevels to AuthenticatorAssuranceLevel.
Realtime enum contracts
packages/realtime_client/lib/src/...
Realtime replaces plural enums and helper extensions with singular enums and enum conversion methods.
Realtime channel integration and validation
packages/realtime_client/lib/src/..., packages/realtime_client/test/...
Channel, client, message, push, and socket code use the renamed enum APIs.
Storage enum and capability metadata
packages/storage_client/lib/src/iceberg/iceberg_types.dart, sdk-compliance.yaml
Iceberg renames LoadTableSnapshots to TableSnapshotScope and updates capability symbols.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The LoadTableSnapshots to TableSnapshotScope rename is outside linked issue #1652, which explicitly says no change is needed for that enum. Remove the storage-client rename from this PR, or link an issue that requires the TableSnapshotScope change.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main changes: singular enum names and folded enum extensions.
Linked Issues check ✅ Passed The PR satisfies the linked objectives for singular enum names, internal annotations, folded extensions, and capability-matrix updates [#1652].
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch v3/singularize-enum-names

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@spydon spydon added the v3 label Aug 5, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/gotrue/lib/src/types/mfa.dart`:
- Line 366: Wrap the documentation comment for the AAL-level declaration near
the visible “Next possible AAL level” text so every Dart source line is no
longer than 80 characters, preserving the existing wording, then run dart format
on the file.

In `@packages/realtime_client/lib/src/types.dart`:
- Around line 69-84: Wrap the long Dart documentation comments in ChannelFilter,
especially the event description and postgresChanges filter description, so
every source line stays within 80 characters. Preserve the existing documented
filter contract and run dart format without changing the surrounding fields or
behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8868351c-b90c-4095-9baa-d53edeb05a5c

📥 Commits

Reviewing files that changed from the base of the PR and between 3e23ddc and 48b9387.

📒 Files selected for processing (21)
  • packages/gotrue/lib/gotrue.dart
  • packages/gotrue/lib/src/constants.dart
  • packages/gotrue/lib/src/gotrue_client.dart
  • packages/gotrue/lib/src/gotrue_mfa_api.dart
  • packages/gotrue/lib/src/types/auth_response.dart
  • packages/gotrue/lib/src/types/mfa.dart
  • packages/gotrue/test/src/constants_test.dart
  • packages/gotrue/test/src/gotrue_mfa_api_test.dart
  • packages/realtime_client/lib/realtime_client.dart
  • packages/realtime_client/lib/src/constants.dart
  • packages/realtime_client/lib/src/message.dart
  • packages/realtime_client/lib/src/push.dart
  • packages/realtime_client/lib/src/realtime_channel.dart
  • packages/realtime_client/lib/src/realtime_client.dart
  • packages/realtime_client/lib/src/transformers.dart
  • packages/realtime_client/lib/src/types.dart
  • packages/realtime_client/test/channel_test.dart
  • packages/realtime_client/test/message_test.dart
  • packages/realtime_client/test/socket_test.dart
  • packages/storage_client/lib/src/iceberg/iceberg_types.dart
  • sdk-compliance.yaml

Comment thread packages/gotrue/lib/src/types/mfa.dart Outdated
Comment thread packages/realtime_client/lib/src/types.dart Outdated
CodeRabbit flagged the AAL and ChannelFilter doc comments in the renamed
declarations for running past 80 columns. Wrap them with the wording unchanged,
and promote the two `AuthenticatorAssuranceLevel` value comments from `//` to
`///` so they actually document the values.
@spydon
spydon merged commit 31c1be3 into main Aug 6, 2026
40 checks passed
@spydon
spydon deleted the v3/singularize-enum-names branch August 6, 2026 07:58
spydon added a commit that referenced this pull request Aug 6, 2026
…olations (#1655)

## Why

`dart format` never reflows comments and never splits string literals,
so nothing enforced the 80-column limit outside of the code the
formatter can break by itself. 440 over-long lines had accumulated
across 109 files, and CodeRabbit was doing the enforcement by hand in
review (it flagged two such lines on #1654).

Enabling the rule continues the ratcheting pattern
`packages/supabase_lints/lib/analysis_options.yaml` already documents:
turn a rule on once its violations are gone.

## What

`lines_longer_than_80_chars: true` in the shared lint config (the
Flutter variant includes it, so both are covered), plus the 440 fixes.

| Category | Count | Treatment |
| --- | --- | --- |
| Prose in `///` / `//` blocks | 281 + 59 | Rewrapped at 80 columns,
wording unchanged |
| Over-long string literals | ~100 | Split into adjacent literals (same
value) |
| Doc code samples | 12 | Reformatted the way `dart format` would break
the same code |
| Missing space after `///` / `//` | 4 | Added, then wrapped |
| Other | 4 | See below |

The four one-offs:

- `buildClientInfoHeader` computes the encoded platform version into a
local instead of interpolating a call chain that cannot fit on one line.
Same output.
- Two `test(...)` headers with a trailing closure moved their arguments
onto separate lines.
- One trailing `// comment` on a map entry moved above the entry.

Three doc samples were JavaScript left over from the ports (`new
RetryTimer(...)`, `console.log(...)`, `let`) inside ` ```dart ` fences.
They are Dart now.

Fenced code, markdown lists and tables, and `{@template}` macros were
kept structurally intact rather than reflowed as prose.

## String values are provably unchanged

Splitting a literal into adjacent literals is value-preserving only if
the split points are the sole change, so that was checked mechanically
rather than by eye: every string literal value in every touched file was
parsed with `package:analyzer` before and after (adjacent literals
collapsed the way the language does) and compared in order. The only
file that reports a difference is `client_info.dart`, which is the
deliberate refactor above.

## A note on the rule

It tolerates a line whose overflow is a single unbreakable URI, verified
with a probe file: a long `'http://…'` literal is accepted, while an
equally long literal without a URI is not. So URLs in comments and
strings stay as they are, and no `// ignore:` comments were needed
anywhere.

## Testing

- `dart analyze packages examples`: clean, zero violations
- `dart format --set-exit-if-changed packages examples`: clean, so the
wrapping is stable under the formatter
- Passing suites: `supabase_common`, `functions_client`,
`realtime_client`, `storage_client`, `supabase`, `supabase_flutter`, and
the hermetic `gotrue` suites (including `get_claims_test` and
`jwk_test`, whose JWT fixtures were split most aggressively, and the two
restructured tests)
- `postgrest` fails against my local stack both on this branch and on
its base, and two identical runs of the same code disagree on which
tests fail, so that suite is state-dependent locally. CI, which starts a
fresh stack, is the arbiter there.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Improved API, security, usage, and example documentation across
authentication, database, realtime, storage, and client libraries.
* Clarified server-only authentication administration guidance and
sign-out event handling.
* Reformatted lengthy comments, examples, messages, and test
descriptions for improved readability and consistency.
* Documented that each JSON isolate instance maintains one running
isolate.
* **Bug Fixes**
  * Improved platform-version metadata encoding while preserving spaces.
* **Chores**
  * Enabled enforcement of an 80-character line-length limit.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
spydon added a commit that referenced this pull request Aug 6, 2026
Closes SDK-1425

## What

v3 is accumulating breaking changes across every package in the monorepo
(#1278), and there is nowhere a user can look to find out what they have
to change in their own code. The changelogs are per package,
auto-generated and one line per commit, so anyone upgrading has to read
seven of them and reconstruct the migration themselves.
`sdk-compliance.yaml` tracks capabilities, not migrations.

This adds a `MIGRATION.md` at the repository root, modelled on [Flame's
migration
guide](https://github.com/flame-engine/flame/blob/main/doc/flame/migration.md):

- One section per major version step, newest first: `## Migrating from
v2 to v3`.
- One `###` subsection per breaking change, titled after what changed.
- Each subsection says why the change was made and what you have to do,
with a `// Before` / `// After` Dart snippet.
- Changes that keep their name but change type or behaviour are called
out explicitly, since those do not surface as compile errors.

One file for the whole monorepo rather than one per package, because the
packages go major in lockstep, and it gives us a single link to hand to
users.

## Covered so far

The two breaking commits that have landed on `main`:

- `RealtimeClient.connectionState` changing from `String` to
`SocketState?` (#1404). This is the silent one: the name is unchanged,
so anyone comparing it against `'open'` gets no compile error.
- The `conn` abbreviations spelled out: `conn` → `connection`,
`connState` → `connectionState`, `onConnMessage` → `onConnectionMessage`
(#1404).
- The four consumer-reachable enum renames (#1654): `SocketStates` →
`SocketState`, `PostgresTypes` → `PostgresType`,
`AuthenticatorAssuranceLevels` → `AuthenticatorAssuranceLevel`,
`LoadTableSnapshots` → `TableSnapshotScope`.

Left out on purpose: the three enums that were never exported
(`ChannelStates`, `ChannelEvents`, `RealtimeListenTypes`) and the enum
extensions folded in by #1654, since all of them are `@internal` and
cannot break a consumer.

The section carries a note that v3 is unreleased and the list is still
growing.

## Keeping it current

`AGENTS.md` now states that a change breaking the public API adds its
own section to `MIGRATION.md` in the same pull request, the same way
parity work reconciles `sdk-compliance.yaml`. There is no pull request
template in `.github/`, so there was nothing to add a checkbox to.

Linked from the root `README.md` and
`packages/supabase_flutter/README.md`, next to the existing Guides and
Reference Docs links.

## Testing

Documentation only, no code changes. Every snippet in the guide was
type-checked against the workspace in a scratch file (`dart analyze`,
clean), which was then deleted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v3: singularize the remaining plural enum names

2 participants