@sentry/api 0.445.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +30 -2
  2. package/dist/api-client/api-path.d.ts +34 -0
  3. package/dist/api-client/auth-token.d.ts +6 -0
  4. package/dist/api-client/core.d.ts +84 -0
  5. package/dist/api-client/endpoints/client-keys.d.ts +38 -0
  6. package/dist/api-client/endpoints/dashboards.d.ts +23 -0
  7. package/dist/api-client/endpoints/index.d.ts +18 -0
  8. package/dist/api-client/endpoints/index.js +762 -0
  9. package/dist/api-client/endpoints/monitors.d.ts +49 -0
  10. package/dist/api-client/endpoints/organizations.d.ts +35 -0
  11. package/dist/api-client/endpoints/profiling.d.ts +32 -0
  12. package/dist/api-client/endpoints/projects.d.ts +63 -0
  13. package/dist/api-client/endpoints/releases.d.ts +45 -0
  14. package/dist/api-client/endpoints/replays.d.ts +53 -0
  15. package/dist/api-client/endpoints/repositories.d.ts +31 -0
  16. package/dist/api-client/endpoints/snapshots.d.ts +29 -0
  17. package/dist/api-client/endpoints/teams.d.ts +23 -0
  18. package/dist/api-client/endpoints/traces.d.ts +25 -0
  19. package/dist/api-client/endpoints/uptime-monitors.d.ts +61 -0
  20. package/dist/api-client/errors.d.ts +151 -0
  21. package/dist/api-client/idempotent-operations.d.ts +33 -0
  22. package/dist/api-client/index.d.ts +20 -0
  23. package/dist/api-client/index.js +1647 -0
  24. package/dist/api-client/pagination.d.ts +119 -0
  25. package/dist/api-client/response-cache/body.d.ts +31 -0
  26. package/dist/api-client/response-cache/index.d.ts +14 -0
  27. package/dist/api-client/response-cache/invalidation.d.ts +42 -0
  28. package/dist/api-client/response-cache/keys.d.ts +25 -0
  29. package/dist/api-client/response-cache/memory-store.d.ts +37 -0
  30. package/dist/api-client/response-cache/policy.d.ts +81 -0
  31. package/dist/api-client/response-cache/store.d.ts +52 -0
  32. package/dist/api-client/response-cache/tiers.d.ts +28 -0
  33. package/dist/api-client/response.d.ts +27 -0
  34. package/dist/api-client/retry.d.ts +57 -0
  35. package/dist/api-client/standard-schema.d.ts +65 -0
  36. package/dist/api-client/time-params.d.ts +46 -0
  37. package/dist/api-client/transport.d.ts +156 -0
  38. package/dist/api-client/validate.d.ts +22 -0
  39. package/dist/zod.gen.d.ts +17150 -96769
  40. package/dist/zod.js +3401 -3401
  41. package/package.json +17 -4
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Limit-bounded, resume-safe pagination over Sentry list endpoints. Pure
3
+ * logic with no I/O, so it runs in Node and Cloudflare Workers. Each product
4
+ * fetches pages, validates rows, logs, and maps failures to its own errors.
5
+ */
6
+ /**
7
+ * Sentry API's maximum items per page. Some endpoints silently cap larger
8
+ * `per_page` values; others (org project list) return 400.
9
+ */
10
+ export declare const API_MAX_PER_PAGE = 100;
11
+ /** One fetched page: its rows and the server's next-page cursor. */
12
+ export type Page<T> = {
13
+ data: T;
14
+ nextCursor?: string;
15
+ };
16
+ /**
17
+ * Where a {@link paginate} walk resumes: the server cursor that fetches the
18
+ * page, the page size it must be fetched with, and how many of that page's
19
+ * rows were already returned.
20
+ */
21
+ export type CursorPosition = {
22
+ /** Server cursor to request; undefined starts at the first page. */
23
+ cursor: string | undefined;
24
+ /** Required page size in rows, when encoded in the cursor; otherwise unspecified. */
25
+ perPage?: number;
26
+ /** Number of rows already returned from this position; zero starts at its first row. */
27
+ skip: number;
28
+ };
29
+ /** Receives a message when a cursor is unreadable and the walk restarts. */
30
+ type Warn = (message: string) => void;
31
+ /**
32
+ * Decode a cursor from {@link paginate}, an older CLI, or an API response.
33
+ *
34
+ * A damaged `cli1~` cursor is ignored with a warning and the walk starts from
35
+ * the first page, so it never fails a call or reaches the API.
36
+ */
37
+ export declare function decodePageCursor(raw: string | undefined, warn?: Warn): CursorPosition;
38
+ /**
39
+ * Consume one fetched page from a decoded cursor position without making requests.
40
+ *
41
+ * Removes rows already delivered by a previous call. Sentry next-page cursors
42
+ * record any unconsumed rows or remaining skip; other cursor shapes are returned
43
+ * unchanged and may replay rows on resume.
44
+ *
45
+ * @param page - Server page fetched using the position's cursor and page size
46
+ * @param position - Decoded continuation for this page
47
+ * @param limit - Maximum rows to return, a non-negative integer; omitted means all remaining rows
48
+ * @returns Remaining rows and continuation metadata
49
+ */
50
+ export declare function consumeCursorPage<T>(page: Page<T[]>, position: CursorPosition, limit?: number): Page<T[]>;
51
+ /** Options for {@link paginate}. */
52
+ export type PaginateOptions = {
53
+ /** Most rows to return. */
54
+ limit: number;
55
+ /** Cursor to resume from: one {@link paginate} returned, or a raw server cursor. */
56
+ cursor?: string;
57
+ /** Most pages to fetch before stopping with a resume cursor. */
58
+ maxPages: number;
59
+ /** Receives a message when `cursor` is unreadable and the walk restarts. */
60
+ warn?: Warn;
61
+ };
62
+ /** Rows from a {@link paginate} walk and where to resume. */
63
+ export type PaginateResult<T> = {
64
+ data: T[];
65
+ /** Resumes at the first row not returned; absent once the server is exhausted. */
66
+ nextCursor?: string;
67
+ /** The walk hit `maxPages` before collecting `limit` rows. */
68
+ stoppedAtPageCap: boolean;
69
+ };
70
+ /**
71
+ * Fetch up to `limit` rows and a cursor that resumes after the last one.
72
+ *
73
+ * - A fresh walk splits `limit` evenly over the fewest requests
74
+ * ({@link pageSizeForLimit}). Resuming a page-number cursor
75
+ * (`OffsetPaginator`, used by projects, teams, members, repositories, and
76
+ * dashboard revisions) reuses the page size the cursor encodes
77
+ * (`<per_page>:<page>:<is_prev>`), whatever the new `limit`: pairing it with
78
+ * another `per_page` reads the wrong window and silently skips rows.
79
+ * - The returned cursor always resumes at the first row the caller has not
80
+ * received. When a walk stops inside a page (a smaller limit, or a server
81
+ * that ignored `per_page`), the cursor refetches that page and skips the
82
+ * rows already returned.
83
+ *
84
+ * Returned cursors are Sentry cursors, so older CLI versions and the API
85
+ * accept them too; mid-page cursors record the rows to skip in `is_prev`
86
+ * ({@link encodeSkip}), which a caller that does not know about them sees
87
+ * again rather than misses (given the page size a page-number cursor
88
+ * encodes). Pass cursors back through this function to resume exactly.
89
+ *
90
+ * Callers own region resolution and query building inside `fetchPage`, and
91
+ * must send `perPage` as the request's `per_page` unchanged.
92
+ *
93
+ * @param options - Limit, start cursor, page cap, and warning sink
94
+ * @param fetchPage - Fetches one page given the page size and a server cursor
95
+ */
96
+ export declare function paginate<T>(options: PaginateOptions, fetchPage: (perPage: number, cursor: string | undefined) => Promise<Page<T[]>>): Promise<PaginateResult<T>>;
97
+ /** Why {@link fetchAllPages} could not return every row. */
98
+ export type FetchAllPagesFailure = "invalid-page" | "repeated-cursor" | "page-cap";
99
+ /** Every row from {@link fetchAllPages}, or why the walk stopped. */
100
+ export type FetchAllPagesResult<T> = {
101
+ ok: true;
102
+ items: T[];
103
+ } | {
104
+ ok: false;
105
+ reason: FetchAllPagesFailure;
106
+ };
107
+ /**
108
+ * Fetch and validate every page of a list endpoint, or report why not.
109
+ *
110
+ * A partial result is a failure: use this when a missing page could hide the
111
+ * record a mutation depends on. Fails on an invalid page, a repeated cursor,
112
+ * or more than `maxPages` pages.
113
+ *
114
+ * @param fetchPage - Fetches one page given a cursor
115
+ * @param parse - Returns a page's validated rows, or `undefined` when invalid
116
+ * @param maxPages - Most pages to fetch
117
+ */
118
+ export declare function fetchAllPages<T>(fetchPage: (cursor: string | undefined) => Promise<Page<unknown>>, parse: (data: unknown) => T[] | undefined, maxPages: number): Promise<FetchAllPagesResult<T>>;
119
+ export {};
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The shape of a stored response body and of the codec that produces it.
3
+ * Hosts implement the codec, since compression needs host APIs such as
4
+ * `node:zlib`, so the cache policy and stores stay portable.
5
+ */
6
+ /** How an entry's body bytes are encoded. */
7
+ export type BodyEncoding = "zstd" | "br" | "identity";
8
+ /** A body as stored: its bytes plus what is needed to decode them. */
9
+ export type EncodedBody = {
10
+ bytes: Uint8Array;
11
+ encoding: BodyEncoding;
12
+ /**
13
+ * Compression dictionary the bytes need. Never set today; recorded so a
14
+ * later dictionary rollout can tell its entries apart from plain ones.
15
+ */
16
+ dictId?: string;
17
+ /** Size of the original body, which bounds decompression. */
18
+ rawSize: number;
19
+ };
20
+ /** Encodes and decodes cached bodies. */
21
+ export type BodyCodec = {
22
+ /** Compress a body for storage. */
23
+ encode(raw: Uint8Array): Promise<EncodedBody>;
24
+ /**
25
+ * Restore a stored body. Returns `undefined` when this runtime cannot read
26
+ * the entry (zstd on Node < 22.15, or a dictionary it does not have), so the
27
+ * caller treats it as a miss. Throws when the bytes are corrupt or do not
28
+ * decode to `rawSize` bytes.
29
+ */
30
+ decode(body: EncodedBody): Promise<Uint8Array | undefined>;
31
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Response cache shared by the CLI and MCP: fallback TTL tiers,
3
+ * identity-scoped keys, mutation invalidation prefixes, HTTP freshness and
4
+ * revalidation, the `CacheStore` interface, and a byte-budgeted memory
5
+ * store. No Node APIs or I/O; hosts with persistent storage implement
6
+ * `CacheStore` themselves.
7
+ */
8
+ export type { BodyCodec, BodyEncoding, EncodedBody } from "./body.js";
9
+ export { computeInvalidationPrefixes } from "./invalidation.js";
10
+ export { buildCacheKey, normalizeUrl } from "./keys.js";
11
+ export { createMemoryStore, type MemoryStore, type MemoryStoreOptions, } from "./memory-store.js";
12
+ export { type CacheLookup, type LookupOptions, lookupResponse, REVALIDATION_WINDOW_MS, type StoreOptions, storeResponse, } from "./policy.js";
13
+ export type { CacheEntry, CacheStore } from "./store.js";
14
+ export { classifyUrl, FALLBACK_TTL_MS, type TtlTier } from "./tiers.js";
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Compute cache-invalidation prefixes for a mutation URL.
3
+ *
4
+ * The host's HTTP layer calls {@link computeInvalidationPrefixes} after
5
+ * every successful non-GET request and deletes the requesting identity's
6
+ * cached entries whose URL starts with any returned prefix. Two rules
7
+ * apply:
8
+ *
9
+ * 1. **Hierarchy walk.** Sweep the URL's own path and every ancestor
10
+ * up to `/api/0/`. A mutation on
11
+ * `/organizations/{org}/releases/1.0.0/deploys/` sweeps itself,
12
+ * `.../releases/1.0.0/`, and `.../releases/` — which catches the
13
+ * detail, deploys-list, and releases-list GET caches in one pass.
14
+ *
15
+ * 2. **Cross-endpoint rules.** A small hardcoded table for mutations
16
+ * whose effects cross URL trees. For example, creating a project
17
+ * under a team hits `/organizations/{org}/teams/{team}/projects/`
18
+ * but invalidates the org project list at
19
+ * `/organizations/{org}/projects/`. The table is tiny today
20
+ * (2 rules) and only grows when a new cross-tree relationship
21
+ * appears in the API surface.
22
+ *
23
+ * Prefixes are identity-scoped at the sweep layer (the store checks each
24
+ * entry's identity before deleting it), so a slightly broader sweep is safe — it can only touch the current
25
+ * identity's entries. Query strings on the mutation URL are dropped
26
+ * from the prefix (a prefix sweep on the path naturally catches every
27
+ * query-param variant cached under that path).
28
+ */
29
+ /**
30
+ * Compute the full set of cache-invalidation prefixes for a mutation
31
+ * URL.
32
+ *
33
+ * @param fullUrl - Fully-qualified URL of the mutation (absolute,
34
+ * including base). Query string is ignored.
35
+ * @param apiBaseUrl - The host's non-region API base URL (used by rules
36
+ * that need to clear caches under a different origin — e.g. the
37
+ * legacy `/issues/{id}/` endpoint the CLI's `getIssue()` reads).
38
+ * @returns Full-URL prefixes to sweep. Returns `[]` if the URL is
39
+ * not under `/api/0/` (e.g. sourcemap chunk upload to an arbitrary
40
+ * endpoint) or can't be parsed.
41
+ */
42
+ export declare function computeInvalidationPrefixes(fullUrl: string, apiBaseUrl: string): string[];
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Identity-scoped cache keys for Sentry API responses. Uses WebCrypto, so it
3
+ * runs in Node, Cloudflare Workers, and browsers.
4
+ */
5
+ /**
6
+ * Normalize method + URL into a stable string for cache key derivation.
7
+ * Keeps the host, so the same path on two Sentry servers gets two keys, and
8
+ * sorts query params by name so `?a=1&b=2` and `?b=2&a=1` match.
9
+ *
10
+ * @throws {TypeError} If the URL cannot be parsed
11
+ */
12
+ export declare function normalizeUrl(method: string, url: string): string;
13
+ /**
14
+ * Build a cache key from the requesting identity, method, and URL: the
15
+ * hex HMAC-SHA256 of {@link normalizeUrl} keyed by `identity`.
16
+ *
17
+ * `identity` scopes entries so one user never receives another's response.
18
+ * It must be a stable hash of who is asking, never a raw token, and should
19
+ * not change when an access token is refreshed for the same login. Keys
20
+ * match `node:crypto`'s `createHmac("sha256", identity)`, so entries written
21
+ * before this module moved here are still found.
22
+ *
23
+ * @throws {TypeError} If `identity` is empty or the URL cannot be parsed
24
+ */
25
+ export declare function buildCacheKey(method: string, url: string, identity: string): Promise<string>;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * In-memory {@link CacheStore} with a byte budget, for the hosted MCP and
3
+ * tests. Evicts least recently used entries first. Holds no timers: expired
4
+ * entries are dropped when read, or evicted like any other entry.
5
+ */
6
+ import type { CacheStore } from "./store.js";
7
+ /**
8
+ * Bytes charged per entry on top of its body, for the key, URL, headers,
9
+ * serialized policy, and bookkeeping. An estimate, so that many small
10
+ * entries (bodies under 256 bytes are stored raw) cannot outgrow the budget.
11
+ */
12
+ export declare const ENTRY_OVERHEAD_BYTES = 1024;
13
+ export type MemoryStoreOptions = {
14
+ /** Budget over all entries, in bytes. Defaults to 24 MiB. */
15
+ maxBytes?: number;
16
+ /** Largest stored (compressed) body, in bytes. Defaults to 1 MiB. */
17
+ maxEntryBytes?: number;
18
+ /**
19
+ * Largest original body, in bytes, which bounds memory while decoding.
20
+ * Defaults to 32 MiB.
21
+ */
22
+ maxRawBytes?: number;
23
+ };
24
+ export type MemoryStore = CacheStore & {
25
+ /** Current entry count and bytes charged against the budget. */
26
+ stats(): {
27
+ entries: number;
28
+ bytes: number;
29
+ };
30
+ };
31
+ /**
32
+ * Create an empty memory store. Entries are kept by reference; callers must
33
+ * not mutate an entry after storing it or one returned by `get`.
34
+ *
35
+ * @throws {RangeError} If a limit is not a positive number
36
+ */
37
+ export declare function createMemoryStore(options?: MemoryStoreOptions): MemoryStore;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * HTTP caching decisions for Sentry API GET responses, through
3
+ * `http-cache-semantics` (RFC 9111). Server cache directives win; a response
4
+ * without them stays fresh for its URL's fallback tier. A stale entry with an
5
+ * `ETag` is kept for a revalidation window and renewed by a matching 304.
6
+ *
7
+ * Works on any `CacheStore` and `BodyCodec` the host passes in, with no Node
8
+ * APIs. The host derives the key, decides whether caching is enabled, and
9
+ * records telemetry around these calls.
10
+ */
11
+ import type { BodyCodec } from "./body.js";
12
+ import type { CacheStore } from "./store.js";
13
+ /**
14
+ * How long a stale entry with an `ETag` is kept for revalidation. Bounded
15
+ * by the store's byte budget like any other entry.
16
+ */
17
+ export declare const REVALIDATION_WINDOW_MS: number;
18
+ /**
19
+ * Result of a lookup that found a usable entry.
20
+ *
21
+ * - `hit`: the entry is fresh; serve `response`. `createdAt` is when the
22
+ * response was received, and `size` is the decoded body size in bytes.
23
+ * - `stale`: the entry is stale but has an `ETag`. Send the request with
24
+ * `conditionalHeaders`, then pass the network response to `revalidate`.
25
+ * On a matching 304 it renews the entry and returns the cached body;
26
+ * otherwise it returns `undefined` and the network response stands (or,
27
+ * for an unusable 304, the caller fetches again without the headers).
28
+ */
29
+ export type CacheLookup = {
30
+ kind: "hit";
31
+ response: Response;
32
+ createdAt: number;
33
+ size: number;
34
+ } | {
35
+ kind: "stale";
36
+ conditionalHeaders: Record<string, string>;
37
+ revalidate(response: Response): Promise<Response | undefined>;
38
+ };
39
+ export type LookupOptions = {
40
+ store: CacheStore;
41
+ codec: BodyCodec;
42
+ /** From `buildCacheKey`, so the entry is scoped to the identity. */
43
+ key: string;
44
+ url: string;
45
+ /** Headers of the new request, for `Vary` matching. */
46
+ requestHeaders: Record<string, string>;
47
+ /** Called when renewing a revalidated entry fails; the response stands. */
48
+ onRenewError?: (error: unknown) => void;
49
+ };
50
+ export type StoreOptions = {
51
+ store: CacheStore;
52
+ codec: BodyCodec;
53
+ /** From `buildCacheKey` for the same identity, method, and URL. */
54
+ key: string;
55
+ /** Recorded on the entry for identity-scoped invalidation. */
56
+ identity: string;
57
+ url: string;
58
+ /** Headers the request was sent with, for `Vary` matching. */
59
+ requestHeaders: Record<string, string>;
60
+ /** The response to cache; its body is consumed. */
61
+ response: Response;
62
+ };
63
+ /**
64
+ * Look up a GET request: a fresh entry is a `hit`, and a stale one with an
65
+ * `ETag` is returned for conditional revalidation.
66
+ *
67
+ * @returns The lookup, or `undefined` on a miss: no entry, a stale entry
68
+ * without an `ETag`, or a body this runtime cannot decode
69
+ * @throws When the stored policy or body is corrupt; the host may drop the
70
+ * entry and treat it as a miss
71
+ */
72
+ export declare function lookupResponse(options: LookupOptions): Promise<CacheLookup | undefined>;
73
+ /**
74
+ * Store a successful GET response when HTTP caching allows it: not for
75
+ * `no-store`, a non-2xx status, or a `no-cache` tier URL. The entry is kept
76
+ * for its freshness lifetime, plus the revalidation window with an `ETag`.
77
+ *
78
+ * @returns The stored (encoded) body size in bytes, or 0 when not stored
79
+ * @throws When the body is not JSON, the only kind cached
80
+ */
81
+ export declare function storeResponse(options: StoreOptions): Promise<number>;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Storage interface for cached Sentry API responses. Backends (memory, the
3
+ * CLI's filesystem, R2) store entries whose bodies are already encoded by
4
+ * the host's `BodyCodec`, and each enforces its own byte budget.
5
+ */
6
+ import type { EncodedBody } from "./body.js";
7
+ import type { TtlTier } from "./tiers.js";
8
+ /** A cached response as a store holds it. */
9
+ export type CacheEntry = {
10
+ /** Full request URL, matched by {@link CacheStore.deleteMatching}. */
11
+ url: string;
12
+ /** Hash of the login that owns the entry; never a raw token. */
13
+ identity: string;
14
+ /** Fallback tier the URL was classified into. */
15
+ tier: TtlTier;
16
+ /** HTTP status of the cached response. */
17
+ status: number;
18
+ /** Response headers kept for callers, such as `Link` for pagination. */
19
+ headers: Readonly<Record<string, string>>;
20
+ /** The response body, encoded by the codec. */
21
+ body: EncodedBody;
22
+ /**
23
+ * The serialized `http-cache-semantics` policy. Stores keep it as is and
24
+ * never read it; `lookupResponse` uses it to decide freshness and
25
+ * revalidation.
26
+ */
27
+ policy: unknown;
28
+ /** When the response was received (epoch ms). */
29
+ createdAt: number;
30
+ };
31
+ /**
32
+ * Where cached responses live. Keys come from `buildCacheKey`, so they are
33
+ * already scoped to an identity.
34
+ */
35
+ export type CacheStore = {
36
+ /** The entry under `key`, or `undefined` if it is missing or expired. */
37
+ get(key: string): Promise<CacheEntry | undefined>;
38
+ /**
39
+ * Store `entry` under `key` for `ttlMs`, replacing any entry already
40
+ * there. `ttlMs` is how long the store keeps the entry, not how long it is
41
+ * fresh: a stale entry with an `ETag` is kept so it can be revalidated. An
42
+ * entry over the store's limits is not stored, and the one it would have
43
+ * replaced is removed, so a later read cannot return the older response.
44
+ */
45
+ set(key: string, entry: CacheEntry, ttlMs: number): Promise<void>;
46
+ /**
47
+ * Remove `identity`'s entries whose URL starts with `urlPrefix`, as
48
+ * returned by `computeInvalidationPrefixes`. Other identities' entries
49
+ * are kept.
50
+ */
51
+ deleteMatching(identity: string, urlPrefix: string): Promise<void>;
52
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Fallback TTL tiers for Sentry API GET responses that carry no HTTP caching
3
+ * headers. Responses with `Cache-Control`, `Expires`, or validators follow
4
+ * those headers instead; the host's cache decides which applies.
5
+ */
6
+ /**
7
+ * TTL tier for a URL.
8
+ *
9
+ * - `stable`: data that changes infrequently (orgs, projects, teams,
10
+ * organization event details, trace-item details)
11
+ * - `volatile`: data that changes often (issues and their events, project
12
+ * event details, full traces, log and span queries)
13
+ * - `no-cache`: never cache (polling endpoints like autofix state)
14
+ *
15
+ * No tier treats a response as immutable. Event payloads embed mutable
16
+ * fields (`nextEventID`, user reports, release data), `latest`/`oldest`/
17
+ * `recommended` resolve to different events over time, and traces gain
18
+ * spans as they arrive (getsentry/sentry#128818).
19
+ */
20
+ export type TtlTier = "stable" | "volatile" | "no-cache";
21
+ /** Fallback TTL durations by tier (milliseconds). `no-cache` uses 0 as a sentinel. */
22
+ export declare const FALLBACK_TTL_MS: Readonly<Record<TtlTier, number>>;
23
+ /**
24
+ * Classify a URL into a TTL tier for fallback caching.
25
+ *
26
+ * @param url - Full URL string (with query params)
27
+ */
28
+ export declare function classifyUrl(url: string): TtlTier;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Reading Sentry API responses. Hosts map what these return to their own
3
+ * errors: the MCP to `ApiError` subclasses, the CLI to its exit-coded ones.
4
+ */
5
+ /** What a failed response's body says, read once. */
6
+ export type ErrorResponseBody = {
7
+ /** The raw body, or undefined when it could not be read. */
8
+ text: string | undefined;
9
+ /** The parsed body, when it is JSON. */
10
+ json?: unknown;
11
+ /** Why the body is not JSON, when it is not. */
12
+ parseError?: string;
13
+ /** The server's `detail` message, when the JSON body has a string one. */
14
+ detail?: string;
15
+ /** True when the body is an HTML page, usually from a proxy or a wrong URL. */
16
+ isHtml: boolean;
17
+ /** Server-requested wait before retrying, from the rate-limit headers. */
18
+ retryAfterMs?: number;
19
+ };
20
+ /** Read the body of a failed response, consuming it. */
21
+ export declare function readErrorResponse(response: Response): Promise<ErrorResponseBody>;
22
+ /**
23
+ * Parse a successful response as JSON, checking its Content-Type first.
24
+ *
25
+ * @throws {Error} When the body is HTML, another content type, or malformed
26
+ */
27
+ export declare function readJsonResponse(response: Response): Promise<unknown>;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Retry policy for Sentry API requests. Pure logic over standard Web APIs, so
3
+ * it runs in Node and Cloudflare Workers. Each product owns its request loop,
4
+ * error classes, and caps; this module decides whether to retry and how long
5
+ * to wait. A 401 credential refresh is not a retry here: the transport may
6
+ * replay any method once after refreshing, because the endpoint never ran.
7
+ */
8
+ /** Caps for one logical request. All delays are in milliseconds. */
9
+ export type RetryPolicy = {
10
+ /** Retries after the first attempt. */
11
+ maxRetries: number;
12
+ /** First fallback backoff step; it doubles on each retry. */
13
+ baseDelayMs: number;
14
+ /** Longest single wait. A server delay above this is not waited for. */
15
+ maxDelayMs: number;
16
+ /** Longest total wait across every retry of the request. */
17
+ maxTotalDelayMs: number;
18
+ };
19
+ type HeaderReader = Pick<Headers, "get">;
20
+ /**
21
+ * Whether a request may be replayed after the endpoint may have run: a
22
+ * transient 5xx, a network error, or a timeout. True for GET, HEAD, and
23
+ * OPTIONS, or when the caller marks the request `idempotent`.
24
+ */
25
+ export declare function isIdempotentRequest(method: string, idempotent?: boolean): boolean;
26
+ /**
27
+ * Milliseconds the response asks the client to wait, or undefined when it
28
+ * gives no usable delay. `Retry-After` (seconds or HTTP-date) wins; a proxy
29
+ * may add it, but Sentry itself does not. Otherwise a 429 waits for
30
+ * `X-Sentry-Rate-Limit-Reset`, the Unix second the next window starts. A
31
+ * concurrency-limit 429 is not tied to the window, so it gets no delay here
32
+ * and the caller falls back to backoff.
33
+ */
34
+ export declare function parseRetryDelayMs(status: number, headers: HeaderReader, now?: number): number | undefined;
35
+ /**
36
+ * Delay before the next retry, or undefined to stop and surface the error.
37
+ * Stops when the method or status is not retryable, the retries are used up,
38
+ * the server delay exceeds `maxDelayMs`, or the wait would exceed
39
+ * `maxTotalDelayMs`.
40
+ */
41
+ export declare function nextRetryDelayMs({ policy, method, idempotent, status, serverDelayMs, attempt, waitedMs, random, }: {
42
+ policy: RetryPolicy;
43
+ method: string;
44
+ idempotent?: boolean;
45
+ /** Failed response status, or undefined for a network error or timeout. */
46
+ status: number | undefined;
47
+ /** From `parseRetryDelayMs` for the failed response. */
48
+ serverDelayMs: number | undefined;
49
+ /** Retries already made for this request, starting at 0. */
50
+ attempt: number;
51
+ /** Total time already spent waiting for this request. */
52
+ waitedMs: number;
53
+ random?: () => number;
54
+ }): number | undefined;
55
+ /** Wait `ms`, or reject with the signal's reason as soon as it aborts. */
56
+ export declare function sleep(ms: number, signal?: AbortSignal | null): Promise<void>;
57
+ export {};
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The Standard Schema V1 interface, copied from `@standard-schema/spec` 1.1.0
3
+ * (MIT, https://standardschema.dev) as the spec invites, so the client
4
+ * accepts Zod, valibot, or any other implementing validator without a
5
+ * dependency. Types only.
6
+ */
7
+ /** The Standard Schema interface. */
8
+ export interface StandardSchemaV1<Input = unknown, Output = Input> {
9
+ /** The Standard Schema properties. */
10
+ readonly "~standard": StandardSchemaV1.Props<Input, Output>;
11
+ }
12
+ export declare namespace StandardSchemaV1 {
13
+ /** The Standard Schema properties interface. */
14
+ interface Props<Input = unknown, Output = Input> {
15
+ /** The version number of the standard. */
16
+ readonly version: 1;
17
+ /** The vendor name of the schema library. */
18
+ readonly vendor: string;
19
+ /** Inferred types associated with the schema. */
20
+ readonly types?: Types<Input, Output> | undefined;
21
+ /** Validates unknown input values. */
22
+ readonly validate: (value: unknown, options?: Options | undefined) => Result<Output> | Promise<Result<Output>>;
23
+ }
24
+ /** The result interface of the validate function. */
25
+ type Result<Output> = SuccessResult<Output> | FailureResult;
26
+ /** The result interface if validation succeeds. */
27
+ interface SuccessResult<Output> {
28
+ /** The typed output value. */
29
+ readonly value: Output;
30
+ /** A falsy value for `issues` indicates success. */
31
+ readonly issues?: undefined;
32
+ }
33
+ interface Options {
34
+ /** Explicit support for additional vendor-specific parameters, if needed. */
35
+ readonly libraryOptions?: Record<string, unknown> | undefined;
36
+ }
37
+ /** The result interface if validation fails. */
38
+ interface FailureResult {
39
+ /** The issues of failed validation. */
40
+ readonly issues: ReadonlyArray<Issue>;
41
+ }
42
+ /** The issue interface of the failure output. */
43
+ interface Issue {
44
+ /** The error message of the issue. */
45
+ readonly message: string;
46
+ /** The path of the issue, if any. */
47
+ readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
48
+ }
49
+ /** The path segment interface of the issue. */
50
+ interface PathSegment {
51
+ /** The key representing a path segment. */
52
+ readonly key: PropertyKey;
53
+ }
54
+ /** The Standard types interface. */
55
+ interface Types<Input = unknown, Output = Input> {
56
+ /** The input type of the schema. */
57
+ readonly input: Input;
58
+ /** The output type of the schema. */
59
+ readonly output: Output;
60
+ }
61
+ /** Infers the input type of a Standard Schema. */
62
+ type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"];
63
+ /** Infers the output type of a Standard Schema. */
64
+ type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
65
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Time range query parameters shared by the endpoints that take one:
3
+ * `statsPeriod` or a `start`/`end` pair, or the `since`/`until` seconds of
4
+ * Sentry's `StatsMixin` endpoints.
5
+ */
6
+ /** A trimmed `statsPeriod`, or undefined when it is blank. */
7
+ export declare function normalizeStatsPeriod(statsPeriod?: string): string | undefined;
8
+ /**
9
+ * The relative period to query: the trimmed `statsPeriod`, or 24 hours when
10
+ * neither it nor an absolute `start` or `end` is given.
11
+ */
12
+ export declare function defaultStatsPeriod({ statsPeriod, start, end, }: {
13
+ statsPeriod?: string;
14
+ start?: string;
15
+ end?: string;
16
+ }): string | undefined;
17
+ /**
18
+ * Split a relative period such as `24h` into its amount and unit.
19
+ *
20
+ * @throws {ApiValidationError} For any other format
21
+ */
22
+ export declare function parseStatsPeriod(statsPeriod: string): {
23
+ amount: number;
24
+ unit: string;
25
+ };
26
+ /**
27
+ * Validates and applies time parameters to a URLSearchParams object.
28
+ *
29
+ * Enforces mutual exclusivity between relative (statsPeriod) and
30
+ * absolute (start/end) time ranges, and ensures start/end are paired.
31
+ *
32
+ * @param queryParams The URLSearchParams to modify
33
+ * @param statsPeriod Relative time period (e.g., "24h", "7d")
34
+ * @param start Absolute start time (ISO 8601)
35
+ * @param end Absolute end time (ISO 8601)
36
+ * @throws {ApiValidationError} If time parameters are invalid
37
+ */
38
+ export declare function applyTimeParams(queryParams: URLSearchParams, statsPeriod?: string, start?: string, end?: string): void;
39
+ /**
40
+ * Like {@link applyTimeParams}, but as the `since` and `until` Unix seconds
41
+ * that `StatsMixin` endpoints read, with an optional `resolution`. A missing
42
+ * range means the last 24 hours.
43
+ *
44
+ * @throws {ApiValidationError} If time parameters are invalid
45
+ */
46
+ export declare function applyStatsMixinTimeParams(queryParams: URLSearchParams, statsPeriod?: string, start?: string, end?: string, resolutionSeconds?: number): void;