|
| export const | RATE_LIMIT_PERIODS |
| | The canonical periods, in ascending order of length.
|
| |
| export const | minute |
| |
| export const | hour |
| |
| export const | day |
| |
| export const | week |
| |
| export const | month |
| |
| export const | year |
| |
| export const const | PERIOD_ALIASES |
| | Every spelling of a period this parser accepts, mapped to its canonical form.
|
| |
| export const const | RateLimitPeriod |
| |
| const | NOISE = /^(?:req|reqs|request|requests|call|calls|hit|hits|api)$/ |
| | Noise words that may sit between the number and the period: 100 req/min, 5000 requests per hour, 60 calls/minute.
|
| |
| export interface | StructuredRateLimit |
| | A limit that could be read as a number and a window.
|
| |
| period | __pad0__ |
| |
| const | rawPeriod = entry.rate_limit_period |
| |
| const | countOk = typeof rawCount === 'number' && Number.isSafeInteger(rawCount) && rawCount >= 0 |
| |
| const | periodOk |
| |
| const | parsed = parseRateLimit(entry.rate_limit) |
| |
| const | legacy = typeof entry.rate_limit === 'string' ? entry.rate_limit.trim() : '' |
| |
| | return |
| |
Rate limits: parsing the free-text form, and rendering the structured one.
A VaultEntry carries the limit twice on purpose. rate_limit_count + rate_limit_period are the structured pair everything reads; rate_limit is a human string kept alongside it so that a vault edited by a current build still means something to an older one, and so a limit nobody can express as <n> per <period> ("varies by endpoint") is not thrown away.
This module is the only thing that converts between the two. It has a twin — unv-cli/src/ratelimit.rs — and the two are pinned against the same golden table in tests/fixtures/parity/rate-limit.json, for the same reason the config exporters are: two implementations of one format drift silently.
| function export parseRateLimit |
( |
|
raw:unknown | ) |
|
Read a free-text rate limit into a count and a period.
Returns null for anything it cannot read with confidence — including a count with no period, which is not a rate limit but a number.
Vault data is untrusted input, so this takes unknown: an old vault, a remote server, or an imported backup can put anything in the field, and the TypeScript type saying string | null is erased at runtime. Render the structured pair as the canonical human string.
Uses the full period name rather than an abbreviation so the output round trips through parseRateLimit — a format that cannot read its own output is how the two halves of an entry drift apart. Normalise whatever an entry carries into the three fields it should carry.
This is the migration, and it runs on read rather than as a one-off pass over the vault: an entry can arrive from an older desktop build, from a remote server running a different version, or from a backup restored years later, and there is no single moment when "the vault has been migrated" is true.
Precedence is structured-wins. If a caller has set count/period those are authoritative and the legacy string is regenerated from them; only when they are absent is the string consulted. Otherwise editing the number in the UI would be silently reverted by a stale string sitting beside it.
| export const const PERIOD_ALIASES |
Every spelling of a period this parser accepts, mapped to its canonical form.
Deliberately generous on input and strict on output. The strings already in people's vaults were typed by hand over years — /min, per hr, a day, req/mo — and a migration that only understood its own output would drop most of them into parseRateLimit's null branch.
| const NOISE = /^(?:req|reqs|request|requests|call|calls|hit|hits|api)$/ |
Noise words that may sit between the number and the period: 100 req/min, 5000 requests per hour, 60 calls/minute.
request and call are here; a unit that changes the meaning — tokens, GB — deliberately is not, because "40000 tokens/min" is not a request limit and silently recording it as one would be wrong. Those fall through to parseRateLimit returning null and are preserved verbatim as a note.