Skip to content

DX-1211: RealtimeChannel interface docstrings#2243

Draft
umair-ably wants to merge 12 commits into
DX-1211/auth-docstringsfrom
DX-1211/realtimechannel-docstrings
Draft

DX-1211: RealtimeChannel interface docstrings#2243
umair-ably wants to merge 12 commits into
DX-1211/auth-docstringsfrom
DX-1211/realtimechannel-docstrings

Conversation

@umair-ably

@umair-ably umair-ably commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Stacked on #2242 (Auth docstrings, base DX-1211/auth-docstrings); review/merge that first. Rewrites the JSDoc on the RealtimeChannel public surface in ably.d.ts per docstringRules.md: terse folded prose that surfaces call-site prerequisites, side-effects, and failure modes (the DX-1211 silent-failure class), with an @see companion link to the canonical reference.

Scope

ably.d.ts only (+135/−29). 19 members rewritten, 2 deliberately left as-is.

Highlights

  • subscribe() (DX-1211 core): documents the silent missing-subscribe-mode trap — the listener never fires, the SDK warn-logs rather than rejecting (or rejects with a hinted ErrorInfo under strictMode). On all four active overloads.
  • params / errorReason: declared non-optional but actually undefined/null until first attach/error — now carry a guard-against-undefined/null caveat (parallel to modes).
  • history(): non-code persistence channel-rule prerequisite; fixes a @param copy-paste bug ("presence members" → "messages").
  • Message ops (getMessage/updateMessage/deleteMessage/appendMessage/getMessageVersions): async reject framing (not synchronous throw) + message-interactions channel-rule prerequisite.
  • push: universal missing-plugin throw kept at the call site; presence/annotations left unchanged (bundled by the default build, so the throw is modular-only).

Validation

npm run docs (TypeDoc treatWarningsAsErrors), prettier --check, and eslint all pass. A clean TypeDoc build confirms every {@link} resolves and nothing became undocumented.

Reviewer notes

  • @see anchors follow the kebab-case convention (matching the Auth PR) but are unverified — ably/docs #3400 isn't live yet and @see is not TypeDoc-validated.
  • A secondary feature-page @see for the five message-interaction members was deliberately omitted pending a confirmed slug.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5292af8e-bbb4-454c-939f-b384ab685b43

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch DX-1211/realtimechannel-docstrings

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.

@github-actions github-actions Bot temporarily deployed to staging/pull/2243/bundle-report June 9, 2026 16:11 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/2243/typedoc June 9, 2026 16:11 Inactive

@m-hulbert m-hulbert left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

A few more comments on this one outside of language. There are some things I think make the descriptions more complicated rather than simpler and a few things to tidy up in terms of naming.

Comment thread ably.d.ts Outdated
readonly name: string;
/**
* An {@link ErrorInfo} object describing the last error which occurred on the channel, if any.
* An {@link ErrorInfo} object describing the last error which occurred on the channel, if any. This is `null` until an error occurs, for example a transition to `failed` or `suspended`, so guard against `null` despite the declared type; inspect it to diagnose a failed or suspended channel.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
* An {@link ErrorInfo} object describing the last error which occurred on the channel, if any. This is `null` until an error occurs, for example a transition to `failed` or `suspended`, so guard against `null` despite the declared type; inspect it to diagnose a failed or suspended channel.
* An {@link ErrorInfo} object describing the last error which occurred on the channel, if any. This is `null` until an error occurs, for example a transition in channel state to `failed` or `suspended`. Guard against `null` despite the declared type and inspect it to diagnose a channel in the failed or suspended state.

Comment thread ably.d.ts Outdated
readonly state: ChannelState;
/**
* Optional [channel parameters](https://ably.com/docs/realtime/channels/channel-parameters/overview) that configure the behavior of the channel.
* Optional [channel parameters](https://ably.com/docs/realtime/channels/channel-parameters/overview) that configure the behavior of the channel. After the channel attaches this reflects the parameters the server confirmed on the most recent attach, which may differ from those requested via {@link ChannelOptions.params}, and is `undefined` before the channel attaches for the first time, so guard against `undefined` despite the declared type.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
* Optional [channel parameters](https://ably.com/docs/realtime/channels/channel-parameters/overview) that configure the behavior of the channel. After the channel attaches this reflects the parameters the server confirmed on the most recent attach, which may differ from those requested via {@link ChannelOptions.params}, and is `undefined` before the channel attaches for the first time, so guard against `undefined` despite the declared type.
* Optional channel parameters that configure the behavior of the channel. After the channel attaches this reflects the parameters the server confirmed on the most recent attach, which may differ from those requested via {@link ChannelOptions.params}. It is `undefined` before the channel attaches for the first time, so guard against `undefined` despite the declared type.

Appreciate this existed before, but it's odd that we link out to the docs on this and the TypeDoc reference and then the @see link is to some different docs again. I think drop the initial link to docs.

Comment thread ably.d.ts Outdated
params: ChannelParams;
/**
* An array of {@link ResolvedChannelMode} objects.
* An array of {@link ResolvedChannelMode} objects reflecting the modes the server granted on the most recent attach, which may differ from the modes requested via {@link ChannelOptions.modes}. The value is `undefined` before the channel attaches for the first time, and is also `undefined` (rather than an empty array) when the server grants no modes, so callers should guard against `undefined` despite the declared type.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

which may differ from the modes requested via {@link ChannelOptions.modes} how and why?

I'd also remove the brackets and long sentences as per other suggestions.

Comment thread ably.d.ts Outdated
modes: ResolvedChannelMode[];
/**
* Deregisters the given listener for the specified event name. This removes an earlier event-specific subscription.
* Deregisters the given listener for the specified event name, removing an earlier event-specific subscription. This only removes the local listener and does not detach the channel, so messages may continue to arrive for any other registered listeners.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think if we're saying other listeners may still be receiving messages then we should also state that messages will still be streamed to the client if they have permissions, unless they detach maybe?

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.

Yes I think we need to be very clear here. It does not detach the channel and any registered listeners may receive messages. But the key part is not detaching the channel - messages will still be sent by the server and will be billed accordingly

Comment thread ably.d.ts Outdated
unsubscribe(event: string, listener: messageCallback<InboundMessage>): void;
/**
* Deregisters the given listener from all event names in the array.
* Deregisters the given listener from all event names in the array. This only removes the local listeners and does not detach the channel.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is there a reason to only include the additional info on 1 overload?

Comment thread ably.d.ts Outdated
history(params: RealtimeHistoryParams | null, callback: StandardCallback<PaginatedResult<InboundMessage>>): never;
/**
* Sets the {@link ChannelOptions} for the channel.
* Sets the {@link ChannelOptions} for the channel. If the channel is already attached or attaching and the new {@link ChannelOptions.modes} or {@link ChannelOptions.params} differ from the current ones, this triggers a live re-attach to apply them, and the returned promise resolves only once the server confirms the new options, rejecting with an {@link ErrorInfo} if the channel detaches or fails in the meantime. Otherwise the new options are stored for the next attach. The promise also rejects with an {@link ErrorInfo} when the supplied options are invalid.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This is a very long sentence and it isn't clear what a "live re-attach" is.

Comment thread ably.d.ts Outdated
setOptions(options: ChannelOptions): Promise<void>;
/**
* Registers a listener for messages with a given event name on this channel. The caller supplies a listener function, which is called each time one or more matching messages arrives on the channel.
* Registers a listener for messages with a given event name on this channel. The caller supplies a listener function, which is called each time one or more matching messages arrives on the channel. Implicitly attaches the channel unless {@link ChannelOptions.attachOnSubscribe} is `false`. Requires the `subscribe` mode (granted by default unless {@link ChannelOptions.modes} excludes it); if the channel attaches without it the server never delivers messages, so the listener silently never fires and a warning is logged rather than the call rejecting (or it rejects with a hinted {@link ErrorInfo} when {@link ClientOptions.strictMode} is enabled).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Mmm, this is a lot of extra info getting into modes here - do you think that's really required?

Comment thread ably.d.ts Outdated
subscribe(event: string, listener: messageCallback<InboundMessage>, callback: ErrorCallback): never;
/**
* Publishes a single message to the channel with the given event name and payload. When publish is called with this client library, it won't attempt to implicitly attach to the channel, so long as [transient publishing](https://ably.com/docs/realtime/channels#transient-publish) is available in the library. Otherwise, the client will implicitly attach.
* Publishes a single message to the channel with the given event name and payload. Publishing does not attach the channel, so unlike {@link RealtimeChannel.subscribe | `subscribe()`}, {@link RealtimePresence.enter | `enter()`}, and {@link RealtimePresence.get | `get()`} a publish-only client need not attach or subscribe first.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I don't think we should be saying unlike X, Y or Z as someone is just looking at this method. If you think we really need to state something, I'd go more along the lines of "the client does not need to attach to the channel before publishing to it", but even that seems redundant to a certain extent.

Comment thread ably.d.ts Outdated
whenState(targetState: ChannelState): Promise<ChannelStateChange | null>;
/**
* Retrieves the latest version of a specific message by its serial identifier.
* Retrieves the latest version of a specific message by its serial identifier. Retrievable messages require message interactions (mutable messages) to be enabled for the channel by a channel rule. The supplied serial or {@link Message} must carry a populated `serial`, which is present on a {@link Message} received from a subscribe callback but not on a freshly constructed one; if the serial is missing the promise rejects with an {@link ErrorInfo}.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We don't call things "mutable messages", "message interactions" nor "channel rules".

'Retrievable messages' also reads strangely - as does what the subsequent sentence is trying to say. I think you're saying serial only exists if you've received a message via subscribe(), not if you've constructed one which is arguable more confusing to read than what it's trying to solve IMO.

Comment thread ably.d.ts Outdated
getMessage(serialOrMessage: string | Message): Promise<Message>;
/**
* Publishes an update to an existing message with patch semantics. Non-null `name`, `data`, and `extras` fields in the provided message will replace the corresponding fields in the existing message, while null fields will be left unchanged.
* Publishes an update to an existing message with patch semantics. Non-null `name`, `data`, and `extras` fields in the provided message will replace the corresponding fields in the existing message, while null fields will be left unchanged. The namespace must have message interactions (updates) enabled by a channel rule, and the supplied `message` must carry the `serial` it was given when published (pass the {@link Message} received in a subscribe callback, not a freshly constructed object); otherwise the promise rejects with an {@link ErrorInfo}.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

As above (haven't been commenting when a previous comment applies to every overload) but also should Message and Serial be capitalised?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

not serial, no. serial is the field on Message (lowercase in the API)

Comment thread ably.d.ts
* ```ts
* const result = await channel.history({ limit: 25 });
* ```
* @see https://ably.com/docs/pub-sub/api/javascript/realtime/realtime-channel#history

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.

A general question - do we have a plan for keeping this in sync with the docs to avoid 404s?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

not directly, the pr description highlights that some of these point at ably/docs PR #3400 which is yet to be merged.

I'll create a ticket to track how we can avoid 404s going forwards, likely some CI step

Comment thread ably.d.ts Outdated
* {@label WITH_MESSAGE_FILTER}
*
* Registers a listener for messages on this channel that match the supplied filter.
* Registers a listener for messages on this channel that match the supplied filter. Implicitly attaches the channel unless {@link ChannelOptions.attachOnSubscribe} is `false`. Requires the `subscribe` mode (granted by default unless {@link ChannelOptions.modes} excludes it); if the channel attaches without it the server never delivers messages, so the listener silently never fires and a warning is logged rather than the call rejecting (or it rejects with a hinted {@link ErrorInfo} when {@link ClientOptions.strictMode} is enabled).

@AndyTWF AndyTWF Jun 24, 2026

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.

Granted by default IFF the key/token has the necessary capability

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fair! I've moved towards keeping things as simple as possible and just mentioned that subscribe is required

Comment thread ably.d.ts Outdated
publish(name: string, data: any, callback: ErrorCallback): never;
/**
* If the channel is already in the given state, returns a promise which immediately resolves to `null`. Else, calls {@link EventEmitter.once | `once()`} to return a promise which resolves the next time the channel transitions to the given state.
* If the channel is already in the given state, returns a promise which immediately resolves to `null`. Else, calls {@link EventEmitter.once | `once()`} to return a promise which resolves with the {@link ChannelStateChange} the next time the channel transitions to the given state.

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.

Calling EventEmitter.once is an internal detail, does the consumer need to know how it works?

Comment thread ably.d.ts Outdated
whenState(targetState: ChannelState): Promise<ChannelStateChange | null>;
/**
* Retrieves the latest version of a specific message by its serial identifier.
* Retrieves the latest version of a specific message by its serial identifier. Retrievable messages require message interactions (mutable messages) to be enabled for the channel by a channel rule. The supplied serial or {@link Message} must carry a populated `serial`, which is present on a {@link Message} received from a subscribe callback but not on a freshly constructed one; if the serial is missing the promise rejects with an {@link ErrorInfo}.

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.

Mutable messages != message interactions - the latter is an unrelated, deprecated feature

Comment thread ably.d.ts Outdated
deleteMessage(message: Message, operation?: MessageOperation, options?: PublishOptions): Promise<UpdateDeleteResult>;
/**
* Appends data to an existing message. The supplied `data` field is appended to the previous message's data, while all other fields (`name`, `extras`) replace the previous values if provided.
* Appends data to an existing message. The supplied `data` field is appended to the previous message's data, while all other fields (`name`, `extras`) replace the previous values if provided. Requires message interactions (mutable messages) to be enabled for the channel by a channel rule, and the supplied {@link Message} must carry the `serial` it received from a subscribe callback, otherwise the call rejects with an {@link ErrorInfo}.

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.

Ditto here and other places mentioning "message interactions" - its unrelated to this

umair-ably added a commit that referenced this pull request Jun 25, 2026
Apply reviewer suggestions and corrections from m-hulbert and AndyTWF:

- errorReason, params, push, history: apply the reviewers' suggested
  wording; drop the inline docs link on params.
- push: state that neither the default nor modular build bundles the
  Push plugin and to import it from `ably/push`; fix naming
  ("push notification", backticked `Push`).
- Remove deprecated/incorrect terms across the message-mutation methods:
  "message interactions" and "channel rule" -> "a rule"; "durable
  storage" -> "storage". State the populated-serial requirement plainly.
- attach/detach: drop internal EventEmitter references, describe the
  emitted state change as prose; add implicit-attach triggers (presence
  update()/get(), LiveObjects get()) and the detaching state; note that
  detaching stops server delivery while local listeners remain; link
  release()/get().
- subscribe: collapse the mode-gate narration to a one-line headline.
- publish: drop the sibling-contrast sentence; unify the verb mood.
- setOptions: remove the "live re-attach" coinage.
- unsubscribe: state the no-detach consequence (server keeps sending,
  billed) consistently across all overloads.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot temporarily deployed to staging/pull/2243/bundle-report June 25, 2026 10:24 Inactive
@github-actions github-actions Bot temporarily deployed to staging/pull/2243/typedoc June 25, 2026 10:24 Inactive
umair-ably and others added 9 commits June 25, 2026 11:45
Declaration only — no runtime use yet. Documented silent-failure paths
will read this option in subsequent commits to gate a hint-carrying
throw; the default stays `false` in v2.x. Per DXRFC-022 work item B5
the default flips to `true` in v3 with no per-call opt-out.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The guard at line 73 parenthesised `(state === 'attached' && _mode & flag) === 0`
so the `=== 0` compared against `(boolean && number)`. It happened to behave
correctly — `false === 0` is `false` so the throw skipped when not attached,
and the bitwise result === 0 was correct when attached — but the comparison
was structural luck rather than the obvious reading of the predicate.
Re-parenthesise to `state === 'attached' && (_mode & flag) === 0`.

Also emit an always-on warning log adjacent to the throw so the diagnostic
fires in the SDK output even when the caller swallows the throw. No
silentFailureLogSuffix here because this throw is unconditional (pre-DXRFC-022)
and not strictMode-gated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A short suffix appended to silent-failure warning logs emitted when
clientOptions.strictMode is off, so the reader knows the same path will
throw in a future major version. Co-locating on Logger keeps the import
surface tight; callers do `Logger.silentFailureLogSuffix()` next to
`Logger.logActionNoStrip(...)`.

Log-only by design — the suffix is not put into ErrorInfo.hint, because
the hint is also shown when the throw fires (strictMode on), where the
suffix would be misleading.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a channel was attached without the presence_subscribe mode, the
server never delivers presence members, so presence.get() resolves to
[] regardless of who is actually present. Today there is no signal
distinguishing "no one is present" from "this client cannot see anyone".

This commit detects the case after ensureAttached() populates the
server-granted mode set, then:

- emits an always-on warning log carrying the hint + a suffix telling
  the reader that strictMode will throw in a future major version.
- throws ErrorInfo with err.hint when clientOptions.strictMode === true.

Code 93002 sits next to 93001 (annotation_subscribe missing) in the
SDK-internal precondition class. It would also be defensible to use
40160 (server-side capability denied), but the hint-coverage rubric
already pins 40160 to the "no auth options" hint shape, so a second
40160 throw site would either weaken that pin or need a rubric refactor.

Suspended-state and {waitForSync: false} paths return earlier and are
unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a channel was attached without the subscribe mode, the server
never delivers messages to the listener, so channel.subscribe()
appears to succeed but no callback ever fires. This commit closes the
gap symmetrically to presence.get() in the previous commit:

- After the implicit attach completes (RTL7g), if subscribe mode was
  not granted by the server, emit an always-on warning log carrying
  the hint + the future-throw suffix.
- One-shot per channel: the warning fires once per attach cycle to
  keep noise down on long-lived listeners. Reset _silentSubscribeWarned
  on the ATTACHED message so a channels.release() + re-attach with
  corrected modes restores signalling.
- Throw ErrorInfo (code 93003) when clientOptions.strictMode === true.

attachOnSubscribe: false is out of scope — the check requires an
attach to have populated _mode. Document this caveat separately if
needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Terser, technical error messages for 93002/93003
- Hints now offer setOptions() or omitting modes + capability check;
  drop confusing channel.modes note
- Keep listener registered on strict-mode throw (matches existing
  subscribe semantics)
- Remove ticket IDs from test names

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…grade

The 93001 hint lumped two distinct failure modes under "if the subsequent
attach is rejected": a missing namespace rule (Mutable Messages) does reject
the attach, but a missing annotation-subscribe capability does NOT - the
server silently drops the mode and this same error re-fires. Confirmed by
live sandbox traces and the canonical error registry.

Reword to key off the symptom the caller observes: attach rejected => enable
the namespace rule; attach succeeds but annotations still undelivered =>
grant the capability. Addresses review feedback that the hint was
presumptuous and over-enumerated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… off colliding 93002

Two fixes to the presence.get()/channel.subscribe() missing-mode errors:

- Hint correctness (review feedback): the presence hint named a
  "presence-subscribe" capability that does not exist. Presence delivery is
  governed by the "subscribe" capability, matching the subscribe-mode hint.

- Error-code collision: 93002 is the canonical server code for "namespace
  needs Mutable Messages" (ably-common errors.json, faqs.ably.com/error-code-93002).
  presence.get() reused it client-side. Move presence to 91008 (presence
  block, next to 91005) and channel.subscribe() to 90009 (channel block);
  93xxx is the annotations/mutable-messages block. Both codes are new on this
  unreleased branch, so the renumber is non-breaking. Reserved in
  ably/ably-common#345. Update the two tests asserting them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ts, failure modes)

Apply docstringRules.md to the public Auth interface in ably.d.ts so silent and
architectural call-site prerequisites are discoverable at the call site:

- revokeTokens: basic-auth (API key, not token) requirement; non-code "revocable
  tokens enabled on the key" prerequisite, with a feature-page @see.
- requestToken: token-issuing prerequisite (authCallback/authUrl/key); callback
  contract detail (content-types, size flags) offloaded to the @see.
- createTokenRequest: a local API key must be available to sign the request.
- authorize: re-authenticates the live connection (resolves once the token takes
  effect on a connected connection), token-issuing prerequisite, and the RSA10a
  key-immutability rule (authorize() cannot change the API key).
- clientId: adds the canonical @see.

Folded prose, no numeric error codes; every behavioural method carries one simple
@example and every member an @see to the canonical JS API reference. TypeDoc
(treatWarningsAsErrors), eslint, and prettier are clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@umair-ably umair-ably force-pushed the DX-1211/auth-docstrings branch from c81b62a to 75ca7f8 Compare June 25, 2026 10:47
umair-ably and others added 2 commits June 25, 2026 11:48
… side-effects, failure modes)

Surface call-site prerequisites and failure modes across the RealtimeChannel
public surface per docstringRules.md (terse folded prose + @see companion):

- subscribe(): silent missing-`subscribe`-mode trap + strictMode aside (DX-1211 core)
- params/errorReason: guard against undefined/null despite the declared type
- history(): persistence channel-rule prerequisite; fix "presence members" @param bug
- message ops (get/update/delete/append/getMessageVersions): async-reject framing
  and message-interactions channel-rule prerequisite
- push: universal missing-plugin throw kept; presence/annotations left as-is (bundled
  by the default build)

TypeDoc (treatWarningsAsErrors), prettier, and eslint all pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Apply reviewer suggestions and corrections from m-hulbert and AndyTWF:

- errorReason, params, push, history: apply the reviewers' suggested
  wording; drop the inline docs link on params.
- push: state that neither the default nor modular build bundles the
  Push plugin and to import it from `ably/push`; fix naming
  ("push notification", backticked `Push`).
- Remove deprecated/incorrect terms across the message-mutation methods:
  "message interactions" and "channel rule" -> "a rule"; "durable
  storage" -> "storage". State the populated-serial requirement plainly.
- attach/detach: drop internal EventEmitter references, describe the
  emitted state change as prose; add implicit-attach triggers (presence
  update()/get(), LiveObjects get()) and the detaching state; note that
  detaching stops server delivery while local listeners remain; link
  release()/get().
- subscribe: collapse the mode-gate narration to a one-line headline.
- publish: drop the sibling-contrast sentence; unify the verb mood.
- setOptions: remove the "live re-attach" coinage.
- unsubscribe: state the no-detach consequence (server keeps sending,
  billed) consistently across all overloads.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@umair-ably umair-ably requested a review from m-hulbert June 25, 2026 11:11
@umair-ably

Copy link
Copy Markdown
Contributor Author

Thanks both - @AndyTWF @m-hulbert

I've heavily refactored the prompt/workflow this was generated from, and introduced a new review step which covers some language and content style guidelines with your feedback from this PR in mind.

Latest commit shows the output of this which I've also checked through. Might still be some stragglers but leaning into this approach so it's easier to apply to all the other docstrings too

@umair-ably umair-ably force-pushed the DX-1211/auth-docstrings branch from 2a86111 to 7906161 Compare June 25, 2026 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants