moderator-toolbox-nxg-for-reddit / modules/shared/proposals/moduleapi
modules/shared/proposals/moduleapi¶
Functions¶
appendProposal()¶
appendProposal(
subreddit,proposal):Promise<ProposalMutationResult>
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:158
Appends a new proposal. Idempotent on id: if a proposal with the same id is already present, no write happens and the existing one is returned.
Parameters¶
subreddit¶
string
The subreddit to write to.
proposal¶
The fully-built proposal (id already assigned).
Returns¶
Promise<ProposalMutationResult>
claimProposalForReplay()¶
claimProposalForReplay(
subreddit,id,reviewer):Promise<ProposalClaimResult>
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:292
Atomically claims a proposal for replay: the conditional wiki write is the
compare-and-set that lets only one of several concurrent reviewers begin the accept,
so an irreversible action can never be replayed twice. Re-checks the accept
preconditions against the fresh page (not the caller’s possibly-stale snapshot):
a now-terminal proposal is already-resolved, a needs_attention proposal that
already landed an irreversible side effect is irreversible-retry, and a proposal
any accept is actively replaying (a live, non-expired claim, even on the same account)
is in-progress. Only an expired claim - a crashed holder - is reclaimable. On
success the returned proposal is the one to replay.
Parameters¶
subreddit¶
string
The subreddit to mutate.
id¶
string
The proposal id.
reviewer¶
string
Username of the accepting moderator.
Returns¶
Promise<ProposalClaimResult>
createProposalId()¶
createProposalId():
string
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:49
Generates a collision-free proposal id.
Returns¶
string
dismissProposal()¶
dismissProposal(
subreddit,id,pruneRetentionDays?):Promise<ProposalMutationResult>
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:409
Marks a resolved proposal as acknowledged by its proposer (clears it from the proposer’s “My proposals” badge and makes it eligible for pruning). Allowed on any existing proposal regardless of status; only the proposer should call this (enforced at the gateway/UI).
When pruneRetentionDays is given, the same write also prunes resolved/acked
proposals past the retention window - so dismissing a resolved proposal removes it
immediately (an acked terminal proposal is always prune-eligible) rather than
lingering until a later maintenance pass.
Parameters¶
subreddit¶
string
The subreddit to mutate.
id¶
string
The proposal id.
pruneRetentionDays?¶
number
Retention window (days) to prune by in the same write, or omit to skip pruning.
Returns¶
Promise<ProposalMutationResult>
loadProposals()¶
loadProposals(
subreddit,opts?):Promise<ProposalsData>
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:68
Reads a subreddit’s proposals for display. Returns the session cache when warm
unless force is set, otherwise fetches canonically and caches the result.
Pure read - never writes the wiki (reconciliation/pruning are explicit
mutations, never side effects of a display read).
Concurrent cold-cache reads of the same subreddit are coalesced into a single wiki fetch (e.g. when many inline badges mount in the same tick), so a queue render does not fire N duplicate reads of the same page before the first one populates the cache.
Parameters¶
subreddit¶
string
The subreddit to load.
opts?¶
force: true bypasses both the cache and the in-flight coalescing.
force?¶
boolean
Returns¶
Promise<ProposalsData>
loadProposalsForSubs()¶
loadProposalsForSubs(
subreddits,opts?):Promise<FanoutResult>
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:126
Reads several subreddits’ proposals concurrently for the cross-subreddit views.
Each subreddit degrades independently: a sub with no proposals page, no wiki
access, or a transient read failure contributes empty data rather than failing the
whole batch (readWikiPageVersioned already maps “no page / no perm” to empty; this
adds a catch for unexpected throws), and its name is collected in failedSubs.
Reads honor the session cache, optionally refreshing entries older than maxAgeMs
so reopening a view re-fetches stale subs without re-scanning fresh ones.
Parameters¶
subreddits¶
readonly string[]
The subreddits to read.
opts?¶
maxAgeMs forces a refetch of caches older than this; concurrency
caps simultaneous reads (default DEFAULT_FANOUT_CONCURRENCY).
concurrency?¶
number
maxAgeMs?¶
number
Returns¶
Promise<FanoutResult>
markProposalObsolete()¶
markProposalObsolete(
subreddit,id,obsoleteReason):Promise<ProposalMutationResult>
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:382
Auto-resolves a proposal to obsolete (target deleted or actioned elsewhere).
Parameters¶
subreddit¶
string
The subreddit to mutate.
id¶
string
The proposal id.
obsoleteReason¶
Why it became obsolete.
Returns¶
Promise<ProposalMutationResult>
pruneResolvedProposals()¶
pruneResolvedProposals(
subreddit,retentionDays,now?):Promise<number>
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:442
Prunes resolved proposals that the proposer has acknowledged, or whose
resolution is older than the subreddit’s retention window. Pending and
needs_attention proposals are always kept. Explicit maintenance call - never
run as a side effect of a display read.
Parameters¶
subreddit¶
string
The subreddit to prune.
retentionDays¶
number
Days to keep a resolved-but-unacknowledged proposal.
now?¶
number = ...
Current epoch seconds (injectable for tests; defaults to now).
Returns¶
Promise<number>
The number of proposals pruned.
rejectProposal()¶
rejectProposal(
subreddit,id,reviewer,feedback?,pruneRetentionDays?):Promise<ProposalMutationResult>
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:355
Rejects a proposal with optional reviewer feedback.
Parameters¶
subreddit¶
string
The subreddit to mutate.
id¶
string
The proposal id.
reviewer¶
string
Username of the rejecting moderator.
feedback?¶
string
Optional explanation shown to the proposer.
pruneRetentionDays?¶
number
Retention window (days) to prune by in the same write, or omit to skip pruning.
Returns¶
Promise<ProposalMutationResult>
releaseProposalClaim()¶
releaseProposalClaim(
subreddit,id,reviewer):Promise<void>
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:334
Releases this reviewer’s replay claim on a proposal (a no-op if they don’t hold it or the proposal is gone), so a perform that failed before resolving the proposal doesn’t block a retry until the claim expires. Resolving the proposal clears the claim on its own - this is only for the abandon/failure paths that leave it pending.
Parameters¶
subreddit¶
string
The subreddit to mutate.
id¶
string
The proposal id.
reviewer¶
string
Username whose claim to release.
Returns¶
Promise<void>
transitionProposal()¶
transitionProposal(
subreddit,id,to,patch,reason,pruneRetentionDays?):Promise<ProposalMutationResult>
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:215
Applies a status transition to one proposal, enforcing canTransition. Internal helper behind rejectProposal/markProposalObsolete and accept/needs-attention (via the gateway).
When pruneRetentionDays is given, the same write that resolves this proposal
also prunes resolved/acked proposals past the retention window - opportunistic
maintenance with no extra I/O, and never as a side effect of a display read. The
just-resolved proposal keeps a fresh resolvedAt, so it is never pruned here.
Parameters¶
subreddit¶
string
The subreddit to mutate.
id¶
string
The proposal id.
to¶
The target status.
patch¶
Partial<Proposal>
Extra fields to set alongside the status (e.g. resolvedBy, feedback).
reason¶
string
The wiki revision note.
pruneRetentionDays?¶
number
Retention window (days) to prune by in the same write, or omit to skip pruning.
Returns¶
Promise<ProposalMutationResult>
Interfaces¶
FanoutResult¶
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:107
The result of a cross-subreddit fan-out: one entry per subreddit (failing subs contribute empty data so the aggregate is always complete) plus the names of the subreddits whose read threw, so the UI can distinguish “no proposals” from “couldn’t load” and offer a targeted retry.
Properties¶
entries¶
entries:
SubredditProposals[]
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:109
One entry per requested subreddit, in request order.
failedSubs¶
failedSubs:
string[]
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:111
Subreddits whose read failed (empty when everything loaded).
Type Aliases¶
ProposalClaimResult¶
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:273
The typed result of a claimProposalForReplay attempt.
ok- this reviewer now holds the claim (proposalis the freshly-claimed state, authoritative for the replay).otherwise
reasonexplains why the claim was refused;currentis the live proposal when one exists (for messaging and to surface who else is mid-accept).
ProposalMutationResult¶
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:43
The typed result of a proposal mutation.
ok- the change was applied (proposalis the new state).otherwise
reasonexplains why nothing changed;currentis the live proposal when one exists (e.g. for “already resolved by u/X” messaging).
Variables¶
SYSTEM_RESOLVER¶
constSYSTEM_RESOLVER:"[system]"='[system]'
Defined in: extension/data/modules/shared/proposals/moduleapi.ts:35
Username sentinel recorded as the resolver when a proposal auto-resolves.