@sentry/api 0.423.0 → 0.425.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.
package/README.md CHANGED
@@ -124,6 +124,43 @@ Each `ApiOperation` records the actual exported `functionName`, original OpenAPI
124
124
 
125
125
  The catalog is generated from the same schema and SDK output as each release. Consumers own search, grouping, ranking, and command aliases; the catalog does not fetch a live schema or infer undocumented API behavior.
126
126
 
127
+ ### Build-time source analysis
128
+
129
+ `@sentry/api/source-analysis` follows references in supplied TypeScript source to discover calls to catalog operations. Install TypeScript only when using this optional build tool; the analyzer is tested with TypeScript 5.9. Its optional peer uses a wildcard so it does not constrain the compiler used by applications that only import the client.
130
+
131
+ ```bash
132
+ npm install --save-dev @sentry/api typescript@^5.9
133
+ ```
134
+
135
+ ```ts
136
+ import { operations } from "@sentry/api/operations";
137
+ import { analyzeSourceApiUsage } from "@sentry/api/source-analysis";
138
+
139
+ const sources = new Map([
140
+ ["features/logs.ts", `
141
+ import { listOrganizationEvents } from "@sentry/api";
142
+ export const readLogs = () =>
143
+ listOrganizationEvents({
144
+ path: { organization_id_or_slug: "example-org" },
145
+ query: { dataset: "logs", field: ["message"] },
146
+ });
147
+ `],
148
+ ]);
149
+ const analysis = analyzeSourceApiUsage(sources, operations, {
150
+ queryParameters: ["dataset"],
151
+ });
152
+ console.log(analysis.exports.get("features/logs.ts")?.get("readLogs")?.operations);
153
+ // Includes listOrganizationEvents with known query context { dataset: "logs" }.
154
+ ```
155
+
156
+ The analyzer parses source without executing it, following local imports, re-exports, aliases, and references. Supply sources together with the operation catalog from the installed SDK version. Run it during the consumer's build: command-to-operation relationships depend on consumer code and cannot be precomputed during SDK packaging.
157
+
158
+ Named, namespace, and default imports are supported, along with top-level functions, variable initializers, and default function/expression exports. Relative imports resolve only against the supplied sources. Extensionless paths try the exact file, `.ts`, `.tsx`, `index.ts`, then `index.tsx`; `.js` specifiers try `.ts` and `.tsx` before the exact `.js` file. Explicit `.ts`/`.tsx` specifiers use the exact file. Named re-exports can forward a default; `export *` forwards only named exports.
159
+
160
+ Consumers configure their own `boundaries` (factory names whose arguments are inspected without following the factory implementation), `requests` (raw-request wrapper argument positions), `queryParameters` (query values to retain), and `declarationFlags` (boolean markers). These options default to empty lists. Returned `boundaries` identify factory-created exports and their markers; `methods` records reachable HTTP methods, including known methods on unresolved raw requests. CLI routing, aliases, presentation, and destructive-command policy remain with the consumer.
161
+
162
+ This is static discovery, not proof of runtime execution or safety. Class/member dispatch, dynamic imports, CommonJS, and `tsconfig` path aliases are outside its scope. Missing sources and unsupported constructs can omit calls, so an empty result does not prove that no API calls exist. `unresolvedRequests` contains diagnostics for raw requests that cannot be resolved against the public catalog, not source-coverage diagnostics. Unknown query values are omitted, mutable `let` and `var` bindings are left unknown, and a related operation does not describe every request a workflow makes. The entry imports TypeScript separately and is not loaded by the root client, browser helpers, or operation catalog.
163
+
127
164
  ### Browser sessions
128
165
 
129
166
  The browser helper configures session cookies and CSRF token injection:
@@ -285,7 +322,7 @@ Sentry uses cursor-based pagination via `Link` headers. Choose one of three help
285
322
  | Task | Method | Result |
286
323
  | --- | --- | --- |
287
324
  | Display one page, with previous/next navigation | `sentry.fetchPage.<operation>(options, cursor?)` | `{ data, response, nextCursor?, prevCursor? }` |
288
- | Collect up to an item limit | `sentry.paginateUpTo.<operation>(options, { limit, ... })` | `{ data, stopReason, nextCursor? }` |
325
+ | Collect up to an item limit | `sentry.paginateUpTo.<operation>(options, { limit, ... })` | `{ data, stopReason, nextCursor?, continuation? }` |
289
326
  | Explicitly collect pages eagerly | `sentry.paginateAll.<operation>(options, { maxPages?, startCursor? }?)` | `{ data, stopReason, nextCursor? }` |
290
327
 
291
328
  `fetchPage` is available for operations whose schema declares a `cursor` query parameter. Collection helpers are available only when the operation's 200 response is an array. Compound response bodies remain intact. Ordinary operation methods such as `sentry.listOrganizations()` still make just one request.
@@ -343,7 +380,59 @@ Automatic sizing is deliberately limited to operations whose forward cursors hav
343
380
 
344
381
  Each request uses the smallest of the remaining item budget, the caller's requested page size (if supplied), and the verified maximum. Other operations retain their query options unchanged. In particular, **projects do not use 100 + 100 + 50**: their backend `OffsetPaginator` includes the page size in its cursor, and resizing mid-traversal can skip rows. Declaring `per_page` in the schema is not enough to enable resizing.
345
382
 
346
- If a server ignores the size or an operation cannot be resized, the helper trims any excess rows and omits the unsafe cursor. It reports `stopReason: "limit"`, even if that was the server's last page. Use `fetchPage` when every row and each page's headers must be retained.
383
+ If a server ignores the size or an operation cannot be resized, the helper trims any excess rows and omits the unsafe server `nextCursor`. It reports `stopReason: "limit"`, even if that was the server's last page. The separate `continuation` retains a position before the pending rows.
384
+
385
+ ### Resume a partially consumed page
386
+
387
+ ```ts
388
+ const options = {
389
+ path: { organization_id_or_slug: "my-org" },
390
+ query: { per_page: 100 },
391
+ };
392
+ const batch = await sentry.paginateUpTo.listOrganizationProjects(options, { limit: 250 });
393
+ // Requests three pages of 100 and returns 250 rows.
394
+ // nextCursor is absent: the next server page would skip the remaining 50.
395
+ if (batch.continuation) {
396
+ const next = await sentry.paginateUpTo.listOrganizationProjects(options, {
397
+ limit: 25,
398
+ resume: batch.continuation,
399
+ });
400
+ // Refetches the third page unchanged and returns its next 25 rows.
401
+ }
402
+ ```
403
+
404
+ `paginateUpTo` returns a `continuation` whenever more rows remain, including on the last server page. Pass it back as `resume`; do not combine it with `startCursor`. At a page boundary it contains the next opaque server `cursor` and `offset: 0`. Within a page it contains the cursor used to fetch that page (absent for the first page), the consumed `offset`, and the original `requestBudget`. It can round-trip through JSON. Keep the same operation, filters, page-size options and fetcher configuration. The SDK does not store credentials, requests or history in it.
405
+
406
+ For standalone `paginateUpTo(fetcher, options, context)`, the callback's second argument is a request budget. It normally equals the remaining item limit. On a partial replay it repeats the original budget so a custom fetcher reconstructs the same request, even when the new batch limit is smaller. After that page, the callback receives the new remaining budget. A callback must retain its own operation-specific sizing rules; the SDK never derives them from the cursor's contents.
407
+
408
+ The standalone collector also accepts a callback returning a normalized `{ data: T[], nextCursor? }` page, including the result of `fetchPage`. Such a callback owns response/error handling and rejects on failure; `request` and `error` are reserved for SDK operation envelopes. Its explicit `nextCursor` is authoritative; the collector does not reinterpret an attached `Response`. SDK operation results retain their existing unwrapping and error behavior. The exported `BudgetedPageFetcher` type is unchanged; `CollectionPageFetcher` describes this additional composition path.
409
+
410
+ ```ts
411
+ import { paginateUpTo } from "@sentry/api";
412
+
413
+ const batch = await paginateUpTo(
414
+ cursor => sentry.fetchPage.listOrganizationProjects(options, cursor),
415
+ { limit: 250 },
416
+ "listOrganizationProjects",
417
+ );
418
+ ```
419
+
420
+ `nextCursor` keeps its existing meaning and can still be sent directly to the API. A `continuation` is SDK state, not a server cursor. Existing single-page, custom-bookmark and infinite-query consumers can continue using ordinary operations or `fetchPage`; neither API changes.
421
+
422
+ ### Consume an already fetched page
423
+
424
+ For a consumer that owns fetching, `consumePage` shares the row-consumption logic without performing I/O or requiring a `Response`:
425
+
426
+ ```ts
427
+ import { consumePage } from "@sentry/api";
428
+
429
+ const page = await sentry.fetchPage.listOrganizationProjects(options, cursor);
430
+ const consumed = consumePage(page, { cursor, offset: 0 }, 25);
431
+ // Keep page.response and any consumer metadata separately.
432
+ // consumed.position identifies where to continue; absence means exhausted.
433
+ ```
434
+
435
+ To resume a position, fetch its cursor with the same page options and pass that position to `consumePage`. A manual `PagePosition` describes row consumption; `paginateUpTo` additionally records the request budget in its `PaginationContinuation`. The caller owns serialization, custom filtering/bookmarks and navigation history. Neither helper snapshots data against concurrent server changes.
347
436
 
348
437
  ### Eager collection and completion
349
438
 
@@ -356,7 +445,7 @@ console.log(projects.data, projects.stopReason);
356
445
  // If stopReason is "maxPages", projects.nextCursor resumes traversal.
357
446
  ```
358
447
 
359
- Both collection helpers return `PaginatedCollection<TItem>`:
448
+ Both collection helpers return `PaginatedCollection<TItem>`. Only `paginateUpTo` supplies the additional `continuation` described above:
360
449
 
361
450
  | `stopReason` | Meaning | `nextCursor` |
362
451
  | --- | --- | --- |
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ export { addOrganizationMember, addOrganizationMemberTeam, addProjectSymbolSourc
2
2
  export type { ActionFilterValidator, AddOrganizationMemberData, AddOrganizationMemberErrors, AddOrganizationMemberResponse, AddOrganizationMemberResponses, AddOrganizationMemberTeamData, AddOrganizationMemberTeamErrors, AddOrganizationMemberTeamResponse, AddOrganizationMemberTeamResponses, AddProjectSymbolSourceData, AddProjectSymbolSourceErrors, AddProjectSymbolSourceResponse, AddProjectSymbolSourceResponses, AddProjectTeamData, AddProjectTeamErrors, AddProjectTeamResponse, AddProjectTeamResponses, ArtifactBundleAssembleResponse, AssembleOrganizationArtifactBundleData, AssembleOrganizationArtifactBundleErrors, AssembleOrganizationArtifactBundleResponse, AssembleOrganizationArtifactBundleResponses, AssembleProjectDebugFilesData, AssembleProjectDebugFilesErrors, AssembleProjectDebugFilesResponse, AssembleProjectDebugFilesResponse2, AssembleProjectDebugFilesResponses, AutofixPostResponse, AutofixStateResponse, BaseDataConditionGroupValidator, BaseDetectorTypeValidator, BaseTeam, BulkCodeMappingsPartialResponse, BulkCodeMappingsRequest, BulkCodeMappingsResponse, BulkEnvironment, BulkUpdateAlerts, BulkUpdateMonitors, BulkUpdateProjectEnvironments, BulkUpsertOrganizationCodeMappingsData, BulkUpsertOrganizationCodeMappingsErrors, BulkUpsertOrganizationCodeMappingsResponse, BulkUpsertOrganizationCodeMappingsResponses, CheckInList, ChunkUpload, ChunkUploadOptionsResponse, ClientOptions, Commit, CommitPatchSet, CommitSerializerResponse, ConfigValidator, CreateExternalIssueRequest, CreateOrganizationCodeMappingData, CreateOrganizationCodeMappingErrors, CreateOrganizationCodeMappingRequest, CreateOrganizationCodeMappingResponse, CreateOrganizationCodeMappingResponses, CreateOrganizationDashboardData, CreateOrganizationDashboardErrors, CreateOrganizationDashboardResponse, CreateOrganizationDashboardResponses, CreateOrganizationDiscoverSavedQueryData, CreateOrganizationDiscoverSavedQueryErrors, CreateOrganizationDiscoverSavedQueryResponse, CreateOrganizationDiscoverSavedQueryResponses, CreateOrganizationExternalUserData, CreateOrganizationExternalUserErrors, CreateOrganizationExternalUserResponse, CreateOrganizationExternalUserResponses, CreateOrganizationForwardingData, CreateOrganizationForwardingErrors, CreateOrganizationForwardingResponse, CreateOrganizationForwardingResponses, CreateOrganizationIssueIntegrationData, CreateOrganizationIssueIntegrationErrors, CreateOrganizationIssueIntegrationResponse, CreateOrganizationIssueIntegrationResponses, CreateOrganizationIssueViewData, CreateOrganizationIssueViewErrors, CreateOrganizationIssueViewResponse, CreateOrganizationIssueViewResponses, CreateOrganizationMonitorData, CreateOrganizationMonitorErrors, CreateOrganizationMonitorResponse, CreateOrganizationMonitorResponses, CreateOrganizationNotificationsActionData, CreateOrganizationNotificationsActionErrors, CreateOrganizationNotificationsActionResponse, CreateOrganizationNotificationsActionResponses, CreateOrganizationProjectData, CreateOrganizationProjectDetectorData, CreateOrganizationProjectDetectorErrors, CreateOrganizationProjectDetectorResponse, CreateOrganizationProjectDetectorResponses, CreateOrganizationProjectErrors, CreateOrganizationProjectResponse, CreateOrganizationProjectResponses, CreateOrganizationReleaseData, CreateOrganizationReleaseDeployData, CreateOrganizationReleaseDeployErrors, CreateOrganizationReleaseDeployResponse, CreateOrganizationReleaseDeployResponses, CreateOrganizationReleaseErrors, CreateOrganizationReleaseResponse, CreateOrganizationReleaseResponse2, CreateOrganizationReleaseResponses, CreateOrganizationSpikeProtectionData, CreateOrganizationSpikeProtectionErrors, CreateOrganizationSpikeProtectionResponses, CreateOrganizationTeamData, CreateOrganizationTeamErrors, CreateOrganizationTeamResponse, CreateOrganizationTeamResponses, CreateOrganizationWorkflowData, CreateOrganizationWorkflowErrors, CreateOrganizationWorkflowResponse, CreateOrganizationWorkflowResponses, CreateProjectCodeOwnersData, CreateProjectCodeOwnersErrors, CreateProjectCodeOwnersResponse, CreateProjectCodeOwnersResponses, CreateProjectCustomInboundFilterData, CreateProjectCustomInboundFilterErrors, CreateProjectCustomInboundFilterResponse, CreateProjectCustomInboundFilterResponses, CreateProjectHookData, CreateProjectHookErrors, CreateProjectHookResponse, CreateProjectHookResponses, CreateProjectKeyData, CreateProjectKeyErrors, CreateProjectKeyResponse, CreateProjectKeyResponses, CreateProjectPreprodSizeAnalysisSkippedStatusCheckData, CreateProjectPreprodSizeAnalysisSkippedStatusCheckErrors, CreateProjectPreprodSizeAnalysisSkippedStatusCheckResponses, CreateProjectPreprodSnapshotSkippedStatusCheckData, CreateProjectPreprodSnapshotSkippedStatusCheckErrors, CreateProjectPreprodSnapshotSkippedStatusCheckResponses, CreateProjectReplayDeletionJobData, CreateProjectReplayDeletionJobErrors, CreateProjectReplayDeletionJobResponse, CreateProjectReplayDeletionJobResponses, CreateProjectUserFeedbackData, CreateProjectUserFeedbackErrors, CreateProjectUserFeedbackResponse, CreateProjectUserFeedbackResponses, CreateReplayDeletionJob, CreateSentryAppInstallationExternalIssueData, CreateSentryAppInstallationExternalIssueErrors, CreateSentryAppInstallationExternalIssueResponse, CreateSentryAppInstallationExternalIssueResponses, CreateTeamExternalTeamData, CreateTeamExternalTeamErrors, CreateTeamExternalTeamResponse, CreateTeamExternalTeamResponses, CreateTeamProjectData, CreateTeamProjectErrors, CreateTeamProjectResponse, CreateTeamProjectResponses, CustomInboundFilter, CustomInboundFilterCondition, CustomInboundFilterWritable, Dashboard, DashboardCreateWidget, DashboardCreateWidgetLayout, DashboardDetails, DashboardDetailsModel, DashboardListResponse, DashboardPermissions, DashboardWidget, DashboardWidgetQuery, DashboardWidgetQueryOnDemand, DataForwarder, DataForwarderResponse, DeleteOrganizationCodeMappingData, DeleteOrganizationCodeMappingErrors, DeleteOrganizationCodeMappingResponse, DeleteOrganizationCodeMappingResponses, DeleteOrganizationDashboardData, DeleteOrganizationDashboardErrors, DeleteOrganizationDashboardResponse, DeleteOrganizationDashboardResponses, DeleteOrganizationDetectorData, DeleteOrganizationDetectorErrors, DeleteOrganizationDetectorResponse, DeleteOrganizationDetectorResponses, DeleteOrganizationDetectorsData, DeleteOrganizationDetectorsErrors, DeleteOrganizationDetectorsResponse, DeleteOrganizationDetectorsResponses, DeleteOrganizationDiscoverSavedQueryData, DeleteOrganizationDiscoverSavedQueryErrors, DeleteOrganizationDiscoverSavedQueryResponse, DeleteOrganizationDiscoverSavedQueryResponses, DeleteOrganizationExternalUserData, DeleteOrganizationExternalUserErrors, DeleteOrganizationExternalUserResponse, DeleteOrganizationExternalUserResponses, DeleteOrganizationForwardingData, DeleteOrganizationForwardingErrors, DeleteOrganizationForwardingResponse, DeleteOrganizationForwardingResponses, DeleteOrganizationIntegrationData, DeleteOrganizationIntegrationErrors, DeleteOrganizationIntegrationResponse, DeleteOrganizationIntegrationResponses, DeleteOrganizationIssueData, DeleteOrganizationIssueErrors, DeleteOrganizationIssueExternalIssueData, DeleteOrganizationIssueExternalIssueErrors, DeleteOrganizationIssueExternalIssueResponse, DeleteOrganizationIssueExternalIssueResponses, DeleteOrganizationIssueIntegrationData, DeleteOrganizationIssueIntegrationError, DeleteOrganizationIssueIntegrationErrors, DeleteOrganizationIssueIntegrationResponse, DeleteOrganizationIssueIntegrationResponses, DeleteOrganizationIssueResponses, DeleteOrganizationIssuesData, DeleteOrganizationIssuesErrors, DeleteOrganizationIssuesResponse, DeleteOrganizationIssuesResponses, DeleteOrganizationMemberData, DeleteOrganizationMemberErrors, DeleteOrganizationMemberResponse, DeleteOrganizationMemberResponses, DeleteOrganizationMemberTeamData, DeleteOrganizationMemberTeamErrors, DeleteOrganizationMemberTeamResponse, DeleteOrganizationMemberTeamResponses, DeleteOrganizationMonitorData, DeleteOrganizationMonitorErrors, DeleteOrganizationMonitorResponses, DeleteOrganizationNotificationsActionData, DeleteOrganizationNotificationsActionResponse, DeleteOrganizationNotificationsActionResponses, DeleteOrganizationPreprodArtifactSnapshotData, DeleteOrganizationPreprodArtifactSnapshotErrors, DeleteOrganizationPreprodArtifactSnapshotResponse, DeleteOrganizationPreprodArtifactSnapshotResponses, DeleteOrganizationReleaseData, DeleteOrganizationReleaseErrors, DeleteOrganizationReleaseFileData, DeleteOrganizationReleaseFileErrors, DeleteOrganizationReleaseFileResponse, DeleteOrganizationReleaseFileResponses, DeleteOrganizationReleaseResponse, DeleteOrganizationReleaseResponses, DeleteOrganizationScimV2GroupData, DeleteOrganizationScimV2GroupErrors, DeleteOrganizationScimV2GroupResponse, DeleteOrganizationScimV2GroupResponses, DeleteOrganizationScimV2UserData, DeleteOrganizationScimV2UserErrors, DeleteOrganizationScimV2UserResponse, DeleteOrganizationScimV2UserResponses, DeleteOrganizationSpikeProtectionsData, DeleteOrganizationSpikeProtectionsErrors, DeleteOrganizationSpikeProtectionsResponses, DeleteOrganizationWorkflowData, DeleteOrganizationWorkflowErrors, DeleteOrganizationWorkflowResponse, DeleteOrganizationWorkflowResponses, DeleteOrganizationWorkflowsData, DeleteOrganizationWorkflowsErrors, DeleteOrganizationWorkflowsResponse, DeleteOrganizationWorkflowsResponses, DeleteProjectCodeOwnersData, DeleteProjectCodeOwnersErrors, DeleteProjectCodeOwnersResponse, DeleteProjectCodeOwnersResponses, DeleteProjectCustomInboundFilterData, DeleteProjectCustomInboundFilterErrors, DeleteProjectCustomInboundFilterResponse, DeleteProjectCustomInboundFilterResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectHookData, DeleteProjectHookErrors, DeleteProjectHookResponse, DeleteProjectHookResponses, DeleteProjectIssuesData, DeleteProjectIssuesErrors, DeleteProjectIssuesResponse, DeleteProjectIssuesResponses, DeleteProjectKeyData, DeleteProjectKeyErrors, DeleteProjectKeyResponse, DeleteProjectKeyResponses, DeleteProjectMonitorData, DeleteProjectMonitorErrors, DeleteProjectMonitorResponses, DeleteProjectReleaseFileData, DeleteProjectReleaseFileErrors, DeleteProjectReleaseFileResponse, DeleteProjectReleaseFileResponses, DeleteProjectReplayData, DeleteProjectReplayErrors, DeleteProjectReplayResponse, DeleteProjectReplayResponses, DeleteProjectResponse, DeleteProjectResponses, DeleteProjectSymbolSourceData, DeleteProjectSymbolSourceErrors, DeleteProjectSymbolSourceResponse, DeleteProjectSymbolSourceResponses, DeleteProjectTeamData, DeleteProjectTeamErrors, DeleteProjectTeamResponse, DeleteProjectTeamResponses, DeleteSentryAppData, DeleteSentryAppErrors, DeleteSentryAppInstallationExternalIssueData, DeleteSentryAppInstallationExternalIssueErrors, DeleteSentryAppInstallationExternalIssueResponse, DeleteSentryAppInstallationExternalIssueResponses, DeleteSentryAppResponse, DeleteSentryAppResponses, DeleteTeamData, DeleteTeamErrors, DeleteTeamExternalTeamData, DeleteTeamExternalTeamErrors, DeleteTeamExternalTeamResponse, DeleteTeamExternalTeamResponses, DeleteTeamResponse, DeleteTeamResponses, Deploy, DeployResponse, DetailedProject, Detector, DiscoverSavedQuery, DiscoverSavedQueryListResponse, DiscoverSavedQueryModel, DynamicSamplingBias, DynamicSdkLoaderOption, Environment, EnvironmentProject, EventAttachmentDetailsResponse, EventIdLookupResponse, ExecuteSentryAppInstallationExternalIssueActionData, ExecuteSentryAppInstallationExternalIssueActionErrors, ExecuteSentryAppInstallationExternalIssueActionResponse, ExecuteSentryAppInstallationExternalIssueActionResponses, ExplorerAutofixRequest, ExternalActor, ExternalIssueLinkResponse, ExternalTeam, ExternalUser, ExternalUserWritable, Filters, GetFlagLogResponse, GetOrganizationChunkUploadOptionsData, GetOrganizationChunkUploadOptionsErrors, GetOrganizationChunkUploadOptionsResponse, GetOrganizationChunkUploadOptionsResponses, GetOrganizationConfigIntegrationsData, GetOrganizationConfigIntegrationsErrors, GetOrganizationConfigIntegrationsResponse, GetOrganizationConfigIntegrationsResponses, GetOrganizationDashboardData, GetOrganizationDashboardErrors, GetOrganizationDashboardResponse, GetOrganizationDashboardResponses, GetOrganizationData, GetOrganizationDetectorData, GetOrganizationDetectorErrors, GetOrganizationDetectorResponse, GetOrganizationDetectorResponses, GetOrganizationDiscoverSavedQueryData, GetOrganizationDiscoverSavedQueryErrors, GetOrganizationDiscoverSavedQueryResponse, GetOrganizationDiscoverSavedQueryResponses, GetOrganizationErrors, GetOrganizationIntegrationData, GetOrganizationIntegrationResponse, GetOrganizationIntegrationResponses, GetOrganizationIssueAutofixStateData, GetOrganizationIssueAutofixStateErrors, GetOrganizationIssueAutofixStateResponse, GetOrganizationIssueAutofixStateResponses, GetOrganizationIssueData, GetOrganizationIssueErrors, GetOrganizationIssueEventData, GetOrganizationIssueEventErrors, GetOrganizationIssueEventResponse, GetOrganizationIssueEventResponses, GetOrganizationIssueIntegrationData, GetOrganizationIssueIntegrationErrors, GetOrganizationIssueIntegrationResponse, GetOrganizationIssueIntegrationResponses, GetOrganizationIssueResponse, GetOrganizationIssueResponses, GetOrganizationIssueTagData, GetOrganizationIssueTagErrors, GetOrganizationIssueTagResponse, GetOrganizationIssueTagResponses, GetOrganizationMemberData, GetOrganizationMemberErrors, GetOrganizationMemberResponse, GetOrganizationMemberResponses, GetOrganizationMonitorData, GetOrganizationMonitorErrors, GetOrganizationMonitorResponse, GetOrganizationMonitorResponses, GetOrganizationNotificationsActionData, GetOrganizationNotificationsActionResponse, GetOrganizationNotificationsActionResponses, GetOrganizationPreprodArtifactInstallDetailsData, GetOrganizationPreprodArtifactInstallDetailsErrors, GetOrganizationPreprodArtifactInstallDetailsResponse, GetOrganizationPreprodArtifactInstallDetailsResponses, GetOrganizationPreprodArtifactSizeAnalysisData, GetOrganizationPreprodArtifactSizeAnalysisErrors, GetOrganizationPreprodArtifactSizeAnalysisResponse, GetOrganizationPreprodArtifactSizeAnalysisResponses, GetOrganizationPreprodArtifactSnapshotData, GetOrganizationPreprodArtifactSnapshotErrors, GetOrganizationPreprodArtifactSnapshotImageData, GetOrganizationPreprodArtifactSnapshotImageErrors, GetOrganizationPreprodArtifactSnapshotImageResponse, GetOrganizationPreprodArtifactSnapshotImageResponses, GetOrganizationPreprodArtifactSnapshotLatestBaseData, GetOrganizationPreprodArtifactSnapshotLatestBaseErrors, GetOrganizationPreprodArtifactSnapshotLatestBaseResponse, GetOrganizationPreprodArtifactSnapshotLatestBaseResponses, GetOrganizationPreprodArtifactSnapshotResponse, GetOrganizationPreprodArtifactSnapshotResponses, GetOrganizationProfilingFlamegraphData, GetOrganizationProfilingFlamegraphErrors, GetOrganizationProfilingFlamegraphResponse, GetOrganizationProfilingFlamegraphResponses, GetOrganizationReleaseData, GetOrganizationReleaseErrors, GetOrganizationReleaseFileData, GetOrganizationReleaseFileErrors, GetOrganizationReleaseFileResponse, GetOrganizationReleaseFileResponses, GetOrganizationReleaseResponse, GetOrganizationReleaseResponses, GetOrganizationReplayCountData, GetOrganizationReplayCountErrors, GetOrganizationReplayCountResponse, GetOrganizationReplayCountResponses, GetOrganizationReplayData, GetOrganizationReplayErrors, GetOrganizationReplayResponse, GetOrganizationReplayResponses, GetOrganizationResponse, GetOrganizationResponses, GetOrganizationScimV2GroupData, GetOrganizationScimV2GroupErrors, GetOrganizationScimV2GroupResponse, GetOrganizationScimV2GroupResponses, GetOrganizationScimV2ResourceTypeData, GetOrganizationScimV2ResourceTypeErrors, GetOrganizationScimV2ResourceTypeResponse, GetOrganizationScimV2ResourceTypeResponses, GetOrganizationScimV2SchemaData, GetOrganizationScimV2SchemaErrors, GetOrganizationScimV2SchemaResponse, GetOrganizationScimV2SchemaResponses, GetOrganizationScimV2ServiceProviderConfigData, GetOrganizationScimV2ServiceProviderConfigErrors, GetOrganizationScimV2ServiceProviderConfigResponse, GetOrganizationScimV2ServiceProviderConfigResponses, GetOrganizationScimV2UserData, GetOrganizationScimV2UserErrors, GetOrganizationScimV2UserResponse, GetOrganizationScimV2UserResponses, GetOrganizationSessionsData, GetOrganizationSessionsErrors, GetOrganizationSessionsResponse, GetOrganizationSessionsResponses, GetOrganizationStatsSummaryData, GetOrganizationStatsSummaryErrors, GetOrganizationStatsSummaryResponse, GetOrganizationStatsSummaryResponses, GetOrganizationTraceData, GetOrganizationTraceErrors, GetOrganizationTraceMetaData, GetOrganizationTraceMetaErrors, GetOrganizationTraceMetaResponse, GetOrganizationTraceMetaResponses, GetOrganizationTraceResponse, GetOrganizationTraceResponses, GetOrganizationWorkflowData, GetOrganizationWorkflowErrors, GetOrganizationWorkflowResponse, GetOrganizationWorkflowResponses, GetProjectCustomInboundFilterData, GetProjectCustomInboundFilterErrors, GetProjectCustomInboundFilterResponse, GetProjectCustomInboundFilterResponses, GetProjectData, GetProjectEnvironmentData, GetProjectEnvironmentErrors, GetProjectEnvironmentResponse, GetProjectEnvironmentResponses, GetProjectErrors, GetProjectEventAttachmentData, GetProjectEventAttachmentErrors, GetProjectEventAttachmentResponse, GetProjectEventAttachmentResponses, GetProjectEventData, GetProjectEventErrors, GetProjectEventResponse, GetProjectEventResponses, GetProjectEventSourceMapDebugData, GetProjectEventSourceMapDebugErrors, GetProjectEventSourceMapDebugResponse, GetProjectEventSourceMapDebugResponses, GetProjectHookData, GetProjectHookErrors, GetProjectHookResponse, GetProjectHookResponses, GetProjectInstallableBuildLatestData, GetProjectInstallableBuildLatestErrors, GetProjectInstallableBuildLatestResponse, GetProjectInstallableBuildLatestResponses, GetProjectKeyData, GetProjectKeyErrors, GetProjectKeyResponse, GetProjectKeyResponses, GetProjectMonitorData, GetProjectMonitorErrors, GetProjectMonitorResponse, GetProjectMonitorResponses, GetProjectOwnershipData, GetProjectOwnershipResponse, GetProjectOwnershipResponses, GetProjectPreprodSizeAnalysisStatusCheckRulesData, GetProjectPreprodSizeAnalysisStatusCheckRulesErrors, GetProjectPreprodSizeAnalysisStatusCheckRulesResponse, GetProjectPreprodSizeAnalysisStatusCheckRulesResponses, GetProjectPreprodSnapshotStatusCheckRulesData, GetProjectPreprodSnapshotStatusCheckRulesErrors, GetProjectPreprodSnapshotStatusCheckRulesResponse, GetProjectPreprodSnapshotStatusCheckRulesResponses, GetProjectProfilingProfileData, GetProjectProfilingProfileErrors, GetProjectProfilingProfileResponse, GetProjectProfilingProfileResponses, GetProjectReleaseFileData, GetProjectReleaseFileErrors, GetProjectReleaseFileResponse, GetProjectReleaseFileResponses, GetProjectReleaseSetupCompletionData, GetProjectReleaseSetupCompletionErrors, GetProjectReleaseSetupCompletionResponse, GetProjectReleaseSetupCompletionResponses, GetProjectReplayDeletionJobData, GetProjectReplayDeletionJobErrors, GetProjectReplayDeletionJobResponse, GetProjectReplayDeletionJobResponses, GetProjectReplayRecordingSegmentData, GetProjectReplayRecordingSegmentErrors, GetProjectReplayRecordingSegmentResponse, GetProjectReplayRecordingSegmentResponses, GetProjectResponse, GetProjectResponses, GetProjectStacktraceLinkData, GetProjectStacktraceLinkErrors, GetProjectStacktraceLinkResponse, GetProjectStacktraceLinkResponses, GetReplay, GetReplayDeletionJob, GetReplayRecordingSegment, GetReplayViewedBy, GetSentryAppData, GetSentryAppInstallationExternalRequestOptionsData, GetSentryAppInstallationExternalRequestOptionsErrors, GetSentryAppInstallationExternalRequestOptionsResponse, GetSentryAppInstallationExternalRequestOptionsResponses, GetSentryAppResponse, GetSentryAppResponses, GetTeamData, GetTeamErrors, GetTeamResponse, GetTeamResponses, GroupDetailsResponse, GroupEventsResponseDict, GroupExternalIssueResponse, GroupHashesResponse, GroupSearchViewPostValidator, GroupSearchViewTimeFilters, GroupUpdateResponse, GroupValidator, InCommitValidator, InstallInfoResponse, IntegrationChannelsResponse, IntegrationChannelValidationResponse, IntegrationIssueConfigResponse, IntegrationRepositoriesResponse, IssueEventDetailsResponse, IssueIntegrationsResponse, IssueLinkConflict, LatestBaseSnapshotResponse, LatestInstallableBuildResponse, Layout, LegacyBrowserFilter, LinkedDashboard, LinkExternalIssueRequest, LinkProjectRepositoryData, LinkProjectRepositoryErrors, LinkProjectRepositoryResponse, LinkProjectRepositoryResponses, ListClientKeysResponse, ListDataForwarderResponse, ListDetectorSerializerResponse, ListEventAttachmentsResponse, ListFlagLogsResponse, ListMemberOnTeamResponse, ListOrganizationAiConversationsData, ListOrganizationAiConversationsErrors, ListOrganizationAiConversationsResponse, ListOrganizationAiConversationsResponse2, ListOrganizationAiConversationsResponses, ListOrganizationClientKeysResponse, ListOrganizationCodeMappingsData, ListOrganizationCodeMappingsErrors, ListOrganizationCodeMappingsResponse, ListOrganizationCodeMappingsResponse2, ListOrganizationCodeMappingsResponses, ListOrganizationCodeownersAssociationsData, ListOrganizationCodeownersAssociationsErrors, ListOrganizationCodeownersAssociationsResponse, ListOrganizationCodeownersAssociationsResponses, ListOrganizationDashboardsData, ListOrganizationDashboardsErrors, ListOrganizationDashboardsResponse, ListOrganizationDashboardsResponses, ListOrganizationDetectorsData, ListOrganizationDetectorsErrors, ListOrganizationDetectorsResponse, ListOrganizationDetectorsResponses, ListOrganizationDiscoverSavedQueriesData, ListOrganizationDiscoverSavedQueriesErrors, ListOrganizationDiscoverSavedQueriesResponse, ListOrganizationDiscoverSavedQueriesResponses, ListOrganizationEnvironmentsData, ListOrganizationEnvironmentsErrors, ListOrganizationEnvironmentsResponse, ListOrganizationEnvironmentsResponses, ListOrganizationEventsData, ListOrganizationEventsDroppedData, ListOrganizationEventsDroppedErrors, ListOrganizationEventsDroppedResponse, ListOrganizationEventsDroppedResponses, ListOrganizationEventsErrors, ListOrganizationEventsResponse, ListOrganizationEventsResponses, ListOrganizationEventsTimeseriesData, ListOrganizationEventsTimeseriesErrors, ListOrganizationEventsTimeseriesResponse, ListOrganizationEventsTimeseriesResponses, ListOrganizationFlagLogsData, ListOrganizationFlagLogsErrors, ListOrganizationFlagLogsResponse, ListOrganizationFlagLogsResponses, ListOrganizationForwardingData, ListOrganizationForwardingResponse, ListOrganizationForwardingResponses, ListOrganizationIntegrationChannelsData, ListOrganizationIntegrationChannelsErrors, ListOrganizationIntegrationChannelsResponse, ListOrganizationIntegrationChannelsResponses, ListOrganizationIntegrationRepositoriesData, ListOrganizationIntegrationRepositoriesErrors, ListOrganizationIntegrationRepositoriesResponse, ListOrganizationIntegrationRepositoriesResponses, ListOrganizationIntegrationResponse, ListOrganizationIntegrationsData, ListOrganizationIntegrationsResponse, ListOrganizationIntegrationsResponses, ListOrganizationIssueEventsData, ListOrganizationIssueEventsErrors, ListOrganizationIssueEventsResponse, ListOrganizationIssueEventsResponses, ListOrganizationIssueExternalIssuesData, ListOrganizationIssueExternalIssuesResponse, ListOrganizationIssueExternalIssuesResponses, ListOrganizationIssueHashesData, ListOrganizationIssueHashesErrors, ListOrganizationIssueHashesResponse, ListOrganizationIssueHashesResponses, ListOrganizationIssueIntegrationsData, ListOrganizationIssueIntegrationsResponse, ListOrganizationIssueIntegrationsResponses, ListOrganizationIssuesData, ListOrganizationIssuesErrors, ListOrganizationIssuesResponse, ListOrganizationIssuesResponses, ListOrganizationIssueTagValuesData, ListOrganizationIssueTagValuesErrors, ListOrganizationIssueTagValuesResponse, ListOrganizationIssueTagValuesResponses, ListOrganizationIssueViewsData, ListOrganizationIssueViewsErrors, ListOrganizationIssueViewsResponse, ListOrganizationIssueViewsResponses, ListOrganizationMemberResponse, ListOrganizationMembersData, ListOrganizationMembersErrors, ListOrganizationMembersResponse, ListOrganizationMembersResponses, ListOrganizationMonitorCheckinsData, ListOrganizationMonitorCheckinsErrors, ListOrganizationMonitorCheckinsResponse, ListOrganizationMonitorCheckinsResponses, ListOrganizationMonitorsData, ListOrganizationMonitorsErrors, ListOrganizationMonitorsResponse, ListOrganizationMonitorsResponses, ListOrganizationNotificationsActionsData, ListOrganizationNotificationsActionsErrors, ListOrganizationNotificationsActionsResponse, ListOrganizationNotificationsActionsResponses, ListOrganizationProfilingChunksData, ListOrganizationProfilingChunksErrors, ListOrganizationProfilingChunksResponse, ListOrganizationProfilingChunksResponses, ListOrganizationProjectKeysData, ListOrganizationProjectKeysErrors, ListOrganizationProjectKeysResponse, ListOrganizationProjectKeysResponses, ListOrganizationProjectsData, ListOrganizationProjectsErrors, ListOrganizationProjectsResponse, ListOrganizationProjectsResponses, ListOrganizationRelayUsageData, ListOrganizationRelayUsageErrors, ListOrganizationRelayUsageResponse, ListOrganizationRelayUsageResponses, ListOrganizationReleaseCommitfilesData, ListOrganizationReleaseCommitfilesErrors, ListOrganizationReleaseCommitfilesResponses, ListOrganizationReleaseCommitsData, ListOrganizationReleaseCommitsErrors, ListOrganizationReleaseCommitsResponse, ListOrganizationReleaseCommitsResponse2, ListOrganizationReleaseCommitsResponses, ListOrganizationReleaseDeploysData, ListOrganizationReleaseDeploysResponse, ListOrganizationReleaseDeploysResponses, ListOrganizationReleaseFilesData, ListOrganizationReleaseFilesErrors, ListOrganizationReleaseFilesResponse, ListOrganizationReleaseFilesResponses, ListOrganizationReleasesData, ListOrganizationReleasesErrors, ListOrganizationReleasesResponse, ListOrganizationReleasesResponse2, ListOrganizationReleasesResponses, ListOrganizationReleaseThresholdStatusesData, ListOrganizationReleaseThresholdStatusesErrors, ListOrganizationReleaseThresholdStatusesResponse, ListOrganizationReleaseThresholdStatusesResponses, ListOrganizationReplaysData, ListOrganizationReplaySelectorsData, ListOrganizationReplaySelectorsErrors, ListOrganizationReplaySelectorsResponse, ListOrganizationReplaySelectorsResponses, ListOrganizationReplaysErrors, ListOrganizationReplaysResponse, ListOrganizationReplaysResponses, ListOrganizationRepoCommitsData, ListOrganizationRepoCommitsErrors, ListOrganizationRepoCommitsResponse, ListOrganizationRepoCommitsResponses, ListOrganizationReposData, ListOrganizationReposErrors, ListOrganizationRepositoriesResponse, ListOrganizationReposResponse, ListOrganizationReposResponses, ListOrganizations, ListOrganizationScimV2GroupsData, ListOrganizationScimV2GroupsErrors, ListOrganizationScimV2GroupsResponse, ListOrganizationScimV2GroupsResponses, ListOrganizationScimV2ResourceTypesData, ListOrganizationScimV2ResourceTypesErrors, ListOrganizationScimV2ResourceTypesResponse, ListOrganizationScimV2ResourceTypesResponses, ListOrganizationScimV2UsersData, ListOrganizationScimV2UsersErrors, ListOrganizationScimV2UsersResponse, ListOrganizationScimV2UsersResponses, ListOrganizationsData, ListOrganizationSentryAppComponentsData, ListOrganizationSentryAppComponentsErrors, ListOrganizationSentryAppComponentsResponse, ListOrganizationSentryAppComponentsResponses, ListOrganizationSentryAppInstallationsData, ListOrganizationSentryAppInstallationsErrors, ListOrganizationSentryAppInstallationsResponse, ListOrganizationSentryAppInstallationsResponses, ListOrganizationSentryAppsData, ListOrganizationSentryAppsResponse, ListOrganizationSentryAppsResponses, ListOrganizationsErrors, ListOrganizationsResponse, ListOrganizationsResponses, ListOrganizationStatsV2Data, ListOrganizationStatsV2Errors, ListOrganizationStatsV2Response, ListOrganizationStatsV2Responses, ListOrganizationTagsData, ListOrganizationTagsErrors, ListOrganizationTagsResponse, ListOrganizationTagsResponse2, ListOrganizationTagsResponses, ListOrganizationTeamsData, ListOrganizationTeamsErrors, ListOrganizationTeamsResponse, ListOrganizationTeamsResponses, ListOrganizationTraceItemAttributesData, ListOrganizationTraceItemAttributesErrors, ListOrganizationTraceItemAttributesResponse, ListOrganizationTraceItemAttributesResponses, ListOrganizationTraceItemsStatsData, ListOrganizationTraceItemsStatsErrors, ListOrganizationTraceItemsStatsResponse, ListOrganizationTraceItemsStatsResponses, ListOrganizationTraceMetricsData, ListOrganizationTraceMetricsErrors, ListOrganizationTraceMetricsResponse, ListOrganizationTraceMetricsResponse2, ListOrganizationTraceMetricsResponses, ListOrganizationUserTeamsData, ListOrganizationUserTeamsErrors, ListOrganizationUserTeamsResponse, ListOrganizationUserTeamsResponses, ListOrganizationWorkflowsData, ListOrganizationWorkflowsErrors, ListOrganizationWorkflowsResponse, ListOrganizationWorkflowsResponses, ListOrgMembersResponse, ListOrgTeamResponse, ListProjectCodeOwnersData, ListProjectCodeOwnersErrors, ListProjectCodeOwnersResponse, ListProjectCodeOwnersResponses, ListProjectCustomInboundFiltersData, ListProjectCustomInboundFiltersErrors, ListProjectCustomInboundFiltersResponse, ListProjectCustomInboundFiltersResponses, ListProjectDebugFilesData, ListProjectDebugFilesErrors, ListProjectDebugFilesResponse, ListProjectDebugFilesResponse2, ListProjectDebugFilesResponses, ListProjectEnvironments, ListProjectEnvironmentsData, ListProjectEnvironmentsErrors, ListProjectEnvironmentsResponse, ListProjectEnvironmentsResponses, ListProjectEventAttachmentsData, ListProjectEventAttachmentsErrors, ListProjectEventAttachmentsResponse, ListProjectEventAttachmentsResponses, ListProjectEventsData, ListProjectEventsErrors, ListProjectEventsResponse, ListProjectEventsResponses, ListProjectFiltersData, ListProjectFiltersErrors, ListProjectFiltersResponse, ListProjectFiltersResponses, ListProjectHooksData, ListProjectHooksErrors, ListProjectHooksResponse, ListProjectHooksResponses, ListProjectIssuesData, ListProjectIssuesErrors, ListProjectIssuesResponse, ListProjectIssuesResponses, ListProjectKeysData, ListProjectKeysErrors, ListProjectKeysResponse, ListProjectKeysResponses, ListProjectMembersData, ListProjectMembersErrors, ListProjectMembersResponse, ListProjectMembersResponses, ListProjectMonitorCheckinsData, ListProjectMonitorCheckinsErrors, ListProjectMonitorCheckinsResponse, ListProjectMonitorCheckinsResponses, ListProjectReleaseCommitsData, ListProjectReleaseCommitsErrors, ListProjectReleaseCommitsResponse, ListProjectReleaseCommitsResponse2, ListProjectReleaseCommitsResponses, ListProjectReleaseFilesData, ListProjectReleaseFilesErrors, ListProjectReleaseFilesResponse, ListProjectReleaseFilesResponses, ListProjectReleasesData, ListProjectReleasesErrors, ListProjectReleasesResponse, ListProjectReleasesResponse2, ListProjectReleasesResponses, ListProjectReplayClicksData, ListProjectReplayClicksErrors, ListProjectReplayClicksResponse, ListProjectReplayClicksResponses, ListProjectReplayDeletionJobsData, ListProjectReplayDeletionJobsErrors, ListProjectReplayDeletionJobsResponse, ListProjectReplayDeletionJobsResponses, ListProjectReplayRecordingSegmentsData, ListProjectReplayRecordingSegmentsErrors, ListProjectReplayRecordingSegmentsResponse, ListProjectReplayRecordingSegmentsResponses, ListProjectReplayViewedByData, ListProjectReplayViewedByErrors, ListProjectReplayViewedByResponse, ListProjectReplayViewedByResponses, ListProjectRepositoriesData, ListProjectRepositoriesResponse, ListProjectRepositoriesResponses, ListProjectStatsData, ListProjectStatsErrors, ListProjectStatsResponse, ListProjectStatsResponses, ListProjectSymbolSourcesData, ListProjectSymbolSourcesErrors, ListProjectSymbolSourcesResponse, ListProjectSymbolSourcesResponses, ListProjectTagValuesData, ListProjectTagValuesErrors, ListProjectTagValuesResponse, ListProjectTagValuesResponses, ListProjectTeamsData, ListProjectTeamsErrors, ListProjectTeamsResponse, ListProjectTeamsResponses, ListProjectUserFeedbackData, ListProjectUserFeedbackErrors, ListProjectUserFeedbackResponse, ListProjectUserFeedbackResponses, ListProjectUsersData, ListProjectUsersErrors, ListProjectUsersResponse, ListProjectUsersResponse2, ListProjectUsersResponses, ListReleaseFiles, ListReleaseSetupSteps, ListReplayClicks, ListReplayDeletionJobs, ListReplayRecordingSegments, ListReplays, ListSeerModelsData, ListSeerModelsResponse, ListSeerModelsResponses, ListSelectors, ListStackCodeMappingPrefixesData, ListStackCodeMappingPrefixesErrors, ListStackCodeMappingPrefixesResponse, ListStackCodeMappingPrefixesResponses, ListTeamMembersData, ListTeamMembersErrors, ListTeamMembersResponse, ListTeamMembersResponses, ListTeamProjectResponse, ListTeamProjectsData, ListTeamProjectsErrors, ListTeamProjectsResponse, ListTeamProjectsResponses, ListTraceItemAttributesResponse, ListWorkflow, MappingItem, Monitor, MonitorList, MonitorValidator, NotificationAction, OrganizationCodeMappingResponse, OrganizationCodeOwnersAssociationsResponse, OrganizationConfigIntegrationsEndpointResponse, OrganizationDetailsPut, OrganizationEnvironmentResponse, OrganizationEventsDroppedResponse, OrganizationEventsResponseDict, OrganizationEventsTimeseriesResponse, OrganizationGroupIndexGetResponse, OrganizationGroupIndexPutResponse, OrganizationIntegrationResponse, OrganizationIssueView, OrganizationIssueViewList, OrganizationMember, OrganizationMemberRequest, OrganizationMemberRequestWritable, OrganizationMemberScim, OrganizationMemberTeam, OrganizationMemberTeamDetails, OrganizationMemberWithRoles, OrganizationProfilingChunksResponse, OrganizationProfilingFlamegraphResponse, OrganizationProjectResponseDict, OrganizationRelayResponse, OrganizationRelease, OrganizationRepositorySettingsResponse, OrganizationSentryAppDetailsResponse, OrganizationStatsSummaryResponse, OrganizationSummary, OrganizationTraceMetaResponse, OrganizationTraceResponse, OrganizationWithProjectsAndTeams, OrgReleaseResponse, OutcomesResponse, OutgoingNotificationAction, PlatformExternalIssueResponse, ProjectAdmin, ProjectCodeOwners, ProjectCodeOwnersCreateRequest, ProjectCodeOwnersList, ProjectCodeOwnersUpdateRequest, ProjectEventDetailsResponse, ProjectEventsResponseDict, ProjectFilterResponse, ProjectKey, ProjectKeyPost, ProjectOwnership, ProjectOwnershipRequest, ProjectPost, ProjectProfilingProfileResponse, ProjectRepoLinkRequest, ProjectRepoLinkResponse, ProjectRepoListResponse, ProjectSizeStatusCheckRulesResponse, ProjectSnapshotStatusCheckRulesResponse, ProjectStats, ProjectSummary, ProjectTeamsResponse, ProjectWithTeam, ProvisionOrganizationScimV2GroupData, ProvisionOrganizationScimV2GroupErrors, ProvisionOrganizationScimV2GroupResponse, ProvisionOrganizationScimV2GroupResponses, ProvisionOrganizationScimV2UserData, ProvisionOrganizationScimV2UserErrors, ProvisionOrganizationScimV2UserResponse, ProvisionOrganizationScimV2UserResponses, RateLimit, ReleaseFile, ReleaseFileResponse, ReleaseFileUpload, ReleaseHeadCommit, ReleaseHeadCommitSerializerDeprecated, ReleaseSerializerWithProjects, ReleaseThresholdStatusResponse, ReplayCounts, ReplayDeletionJobCreate, ReplayDeletionJobCreateData, RepositoryProjectPathConfig, RepositorySettings, ResolveOrganizationEventIdData, ResolveOrganizationEventIdErrors, ResolveOrganizationEventIdResponse, ResolveOrganizationEventIdResponses, ResolveOrganizationShortIdData, ResolveOrganizationShortIdErrors, ResolveOrganizationShortIdResponse, ResolveOrganizationShortIdResponses, RetrieveOrganizationAiConversationData, RetrieveOrganizationAiConversationErrors, RetrieveOrganizationAiConversationResponse, RetrieveOrganizationAiConversationResponse2, RetrieveOrganizationAiConversationResponses, RetrieveOrganizationFlagLogData, RetrieveOrganizationFlagLogErrors, RetrieveOrganizationFlagLogResponse, RetrieveOrganizationFlagLogResponses, RetrieveProjectCodeOwnersData, RetrieveProjectCodeOwnersErrors, RetrieveProjectCodeOwnersResponse, RetrieveProjectCodeOwnersResponses, ScimListResourceTypesResponse, ScimListResponseEnvelopeScimMemberIndexResponse, ScimListResponseEnvelopeScimTeamIndexResponse, ScimMemberProvision, ScimPatchOperation, ScimPatchRequest, ScimResourceTypeResponse, ScimSchemaResponse, ScimServiceProviderConfigResponse, ScimTeamPatchOperation, ScimTeamPatchRequest, ScimTeamRequestBody, SeerModelsResponse, SentryAppComponentsResponse, SentryAppDetailsResponse, SentryAppExternalRequestOptionsResponse, SentryAppInstallationExternalIssueActions, SentryAppParser, SessionsQueryResult, ShortIdLookupResponse, SizeAnalysisResponse, SkipStatusCheck, SnapshotCreateResponse, SnapshotDetailsResponse, SnapshotImageDetailResponse, Source, SourceMapDebug, StackPrefixesResponse, StacktraceLinkResponse, StarOrganizationServiceSpanData, StarOrganizationServiceSpanErrors, StarOrganizationServiceSpanResponses, StarSegment, StartOrganizationIssueAutofixData, StartOrganizationIssueAutofixErrors, StartOrganizationIssueAutofixResponse, StartOrganizationIssueAutofixResponses, StatusDetailsValidator, TagKeyDetailsDict, TagKeyValuesDict, Team, TeamDetails, TeamPost, TeamScim, TraceItemStatsResponse, UnstarOrganizationServiceSpanData, UnstarOrganizationServiceSpanErrors, UnstarOrganizationServiceSpanResponses, UpdateClientKey, UpdateOrganizationCodeMappingData, UpdateOrganizationCodeMappingErrors, UpdateOrganizationCodeMappingResponse, UpdateOrganizationCodeMappingResponses, UpdateOrganizationDashboardData, UpdateOrganizationDashboardErrors, UpdateOrganizationDashboardResponse, UpdateOrganizationDashboardResponses, UpdateOrganizationData, UpdateOrganizationDetectorData, UpdateOrganizationDetectorErrors, UpdateOrganizationDetectorResponse, UpdateOrganizationDetectorResponses, UpdateOrganizationDetectorsData, UpdateOrganizationDetectorsErrors, UpdateOrganizationDetectorsResponse, UpdateOrganizationDetectorsResponses, UpdateOrganizationDiscoverSavedQueryData, UpdateOrganizationDiscoverSavedQueryErrors, UpdateOrganizationDiscoverSavedQueryResponse, UpdateOrganizationDiscoverSavedQueryResponses, UpdateOrganizationErrors, UpdateOrganizationExternalUserData, UpdateOrganizationExternalUserErrors, UpdateOrganizationExternalUserResponse, UpdateOrganizationExternalUserResponses, UpdateOrganizationForwardingData, UpdateOrganizationForwardingErrors, UpdateOrganizationForwardingResponse, UpdateOrganizationForwardingResponses, UpdateOrganizationIssueData, UpdateOrganizationIssueErrors, UpdateOrganizationIssueIntegrationData, UpdateOrganizationIssueIntegrationError, UpdateOrganizationIssueIntegrationErrors, UpdateOrganizationIssueIntegrationResponse, UpdateOrganizationIssueIntegrationResponses, UpdateOrganizationIssueResponse, UpdateOrganizationIssueResponses, UpdateOrganizationIssuesData, UpdateOrganizationIssuesErrors, UpdateOrganizationIssuesResponse, UpdateOrganizationIssuesResponses, UpdateOrganizationMemberData, UpdateOrganizationMemberErrors, UpdateOrganizationMemberResponse, UpdateOrganizationMemberResponses, UpdateOrganizationMemberTeamData, UpdateOrganizationMemberTeamErrors, UpdateOrganizationMemberTeamResponse, UpdateOrganizationMemberTeamResponses, UpdateOrganizationMonitorData, UpdateOrganizationMonitorErrors, UpdateOrganizationMonitorResponse, UpdateOrganizationMonitorResponses, UpdateOrganizationNotificationsActionData, UpdateOrganizationNotificationsActionErrors, UpdateOrganizationNotificationsActionResponse, UpdateOrganizationNotificationsActionResponses, UpdateOrganizationReleaseData, UpdateOrganizationReleaseErrors, UpdateOrganizationReleaseFileData, UpdateOrganizationReleaseFileErrors, UpdateOrganizationReleaseFileResponse, UpdateOrganizationReleaseFileResponses, UpdateOrganizationReleaseResponse, UpdateOrganizationReleaseResponses, UpdateOrganizationRepositorySettingsData, UpdateOrganizationRepositorySettingsErrors, UpdateOrganizationRepositorySettingsResponse, UpdateOrganizationRepositorySettingsResponses, UpdateOrganizationResponse, UpdateOrganizationResponses, UpdateOrganizationScimV2GroupData, UpdateOrganizationScimV2GroupErrors, UpdateOrganizationScimV2GroupResponse, UpdateOrganizationScimV2GroupResponses, UpdateOrganizationScimV2UserData, UpdateOrganizationScimV2UserErrors, UpdateOrganizationScimV2UserResponse, UpdateOrganizationScimV2UserResponses, UpdateOrganizationWorkflowData, UpdateOrganizationWorkflowErrors, UpdateOrganizationWorkflowResponse, UpdateOrganizationWorkflowResponses, UpdateOrganizationWorkflowsData, UpdateOrganizationWorkflowsErrors, UpdateOrganizationWorkflowsResponse, UpdateOrganizationWorkflowsResponses, UpdateOrgMemberRoles, UpdateProjectCodeOwnersData, UpdateProjectCodeOwnersErrors, UpdateProjectCodeOwnersResponse, UpdateProjectCodeOwnersResponses, UpdateProjectCustomInboundFilterData, UpdateProjectCustomInboundFilterErrors, UpdateProjectCustomInboundFilterResponse, UpdateProjectCustomInboundFilterResponses, UpdateProjectData, UpdateProjectEnvironmentData, UpdateProjectEnvironmentErrors, UpdateProjectEnvironmentResponse, UpdateProjectEnvironmentResponses, UpdateProjectEnvironmentsData, UpdateProjectEnvironmentsErrors, UpdateProjectEnvironmentsResponse, UpdateProjectEnvironmentsResponses, UpdateProjectErrors, UpdateProjectFilterData, UpdateProjectFilterErrors, UpdateProjectFilterResponse, UpdateProjectFilterResponses, UpdateProjectHookData, UpdateProjectHookErrors, UpdateProjectHookResponse, UpdateProjectHookResponses, UpdateProjectIssuesData, UpdateProjectIssuesErrors, UpdateProjectIssuesResponse, UpdateProjectIssuesResponses, UpdateProjectKeyData, UpdateProjectKeyErrors, UpdateProjectKeyResponse, UpdateProjectKeyResponses, UpdateProjectMonitorData, UpdateProjectMonitorErrors, UpdateProjectMonitorResponse, UpdateProjectMonitorResponses, UpdateProjectOwnershipData, UpdateProjectOwnershipErrors, UpdateProjectOwnershipResponse, UpdateProjectOwnershipResponses, UpdateProjectReleaseFileData, UpdateProjectReleaseFileErrors, UpdateProjectReleaseFileResponse, UpdateProjectReleaseFileResponses, UpdateProjectResponse, UpdateProjectResponses, UpdateProjectSymbolSourceData, UpdateProjectSymbolSourceErrors, UpdateProjectSymbolSourceResponse, UpdateProjectSymbolSourceResponses, UpdateSentryAppData, UpdateSentryAppErrors, UpdateSentryAppResponse, UpdateSentryAppResponses, UpdateTeamData, UpdateTeamErrors, UpdateTeamExternalTeamData, UpdateTeamExternalTeamErrors, UpdateTeamExternalTeamResponse, UpdateTeamExternalTeamResponses, UpdateTeamResponse, UpdateTeamResponses, UploadOrganizationChunksData, UploadOrganizationChunksErrors, UploadOrganizationChunksResponses, UploadOrganizationReleaseFileData, UploadOrganizationReleaseFileErrors, UploadOrganizationReleaseFileResponse, UploadOrganizationReleaseFileResponses, UploadProjectPreprodArtifactSnapshotData, UploadProjectPreprodArtifactSnapshotErrors, UploadProjectPreprodArtifactSnapshotResponse, UploadProjectPreprodArtifactSnapshotResponses, UploadProjectReleaseFileData, UploadProjectReleaseFileErrors, UploadProjectReleaseFileResponse, UploadProjectReleaseFileResponses, ValidateOrganizationIntegrationChannelData, ValidateOrganizationIntegrationChannelErrors, ValidateOrganizationIntegrationChannelResponse, ValidateOrganizationIntegrationChannelResponses, WidgetLayout, Workflow, WorkflowValidator } from './types.gen';
3
3
  export { callWithTypedErrors, narrowError, SentryApiError } from './sentry-errors.ts';
4
4
  export type { DocumentedSentryApiError, NarrowedResult, SentryApiResultError, SentryApiTransportError, SdkResult, UndocumentedSentryApiError } from './sentry-errors.ts';
5
- export { parseSentryLinkHeader, unwrapResult, unwrapPaginatedResult, fetchPage, paginateAll, paginateUpTo } from './sentry-pagination.ts';
6
- export type { UnwrappedResult, PaginatedResponse, PaginatedCollection, PaginateAllOptions, PaginateUpToOptions, PageFetcher, BudgetedPageFetcher } from './sentry-pagination.ts';
5
+ export { parseSentryLinkHeader, unwrapResult, unwrapPaginatedResult, fetchPage, paginateAll, paginateUpTo, consumePage } from './sentry-pagination.ts';
6
+ export type { UnwrappedResult, PaginatedResponse, PaginatedCollection, PaginateAllOptions, PaginateUpToOptions, PageFetcher, BudgetedPageFetcher, CollectionPage, CollectionPageFetcher, PagePosition, PaginationContinuation } from './sentry-pagination.ts';
7
7
  export * from './error-results.gen.ts';
8
8
  export type * from './query-enums.gen.ts';
9
9
  export * from './pagination.gen.ts';
package/dist/index.js CHANGED
@@ -2540,6 +2540,32 @@ function assertPositiveInteger(value, name) {
2540
2540
  throw new Error(`${name} must be a positive safe integer, got ${value}`);
2541
2541
  }
2542
2542
  }
2543
+ function assertPagePosition(position) {
2544
+ if (!Number.isSafeInteger(position.offset) || position.offset < 0) {
2545
+ throw new Error(`pagination: offset must be a non-negative safe integer, got ${position.offset}`);
2546
+ }
2547
+ if (position.cursor !== undefined && typeof position.cursor !== "string") {
2548
+ throw new Error("pagination: cursor must be a string");
2549
+ }
2550
+ }
2551
+ function consumePage(page, position, limit = Number.POSITIVE_INFINITY) {
2552
+ assertPagePosition(position);
2553
+ if (limit !== Number.POSITIVE_INFINITY && (!Number.isSafeInteger(limit) || limit < 0)) {
2554
+ throw new Error(`consumePage: limit must be a non-negative safe integer, got ${limit}`);
2555
+ }
2556
+ const end = Math.min(page.data.length, position.offset + limit);
2557
+ const data = page.data.slice(position.offset, end);
2558
+ if (end < page.data.length) {
2559
+ return { data, position: { ...position, offset: end } };
2560
+ }
2561
+ if (page.nextCursor !== undefined) {
2562
+ return {
2563
+ data,
2564
+ position: { cursor: page.nextCursor, offset: Math.max(0, position.offset - page.data.length) }
2565
+ };
2566
+ }
2567
+ return { data };
2568
+ }
2543
2569
  var parseSentryLinkHeader = (header) => {
2544
2570
  if (!header) {
2545
2571
  return {};
@@ -2649,26 +2675,48 @@ var paginateUpTo = async (fetcher, options, context) => {
2649
2675
  assertPositiveInteger(options.limit, "paginateUpTo: limit");
2650
2676
  const maxPages = options.maxPages ?? 50;
2651
2677
  assertPositiveInteger(maxPages, "paginateUpTo: maxPages");
2678
+ if (options.resume !== undefined && options.startCursor !== undefined) {
2679
+ throw new Error("paginateUpTo: use either resume or startCursor, not both");
2680
+ }
2681
+ if (options.resume !== undefined) {
2682
+ assertPagePosition(options.resume);
2683
+ if (options.resume.offset > 0 || options.resume.requestBudget !== undefined) {
2684
+ assertPositiveInteger(options.resume.requestBudget, "paginateUpTo: resume.requestBudget");
2685
+ }
2686
+ }
2652
2687
  const allItems = [];
2653
- let cursor = options.startCursor;
2688
+ let position = options.resume ?? { cursor: options.startCursor, offset: 0 };
2689
+ let replayBudget = options.resume?.offset ? options.resume.requestBudget : undefined;
2690
+ let continuation;
2654
2691
  for (let page = 0;page < maxPages; page++) {
2655
2692
  const remaining = options.limit - allItems.length;
2656
- const result = await fetcher(cursor, remaining);
2657
- const { data, nextCursor } = unwrapPaginatedResult(result, context);
2658
- allItems.push(...data.slice(0, remaining));
2693
+ const requestBudget = replayBudget ?? remaining;
2694
+ const result = await fetcher(position.cursor, requestBudget);
2695
+ const { data, nextCursor } = result.request !== undefined ? unwrapPaginatedResult(result, context) : result;
2696
+ const consumed = consumePage({ data, nextCursor }, position, remaining);
2697
+ allItems.push(...consumed.data);
2659
2698
  options.onPage?.(allItems.length, options.limit);
2660
- if (data.length > remaining) {
2661
- return { data: allItems, stopReason: "limit" };
2662
- }
2663
- if (nextCursor === undefined) {
2699
+ if (consumed.position === undefined) {
2664
2700
  return { data: allItems, stopReason: "exhausted" };
2665
2701
  }
2702
+ position = consumed.position;
2703
+ continuation = position.offset === 0 ? { ...position, offset: 0 } : { ...position, requestBudget };
2666
2704
  if (allItems.length === options.limit) {
2667
- return { data: allItems, stopReason: "limit", nextCursor };
2705
+ return {
2706
+ data: allItems,
2707
+ stopReason: "limit",
2708
+ ...position.offset === 0 && position.cursor !== undefined ? { nextCursor: position.cursor } : {},
2709
+ continuation
2710
+ };
2668
2711
  }
2669
- cursor = nextCursor;
2712
+ replayBudget = position.offset > 0 ? requestBudget : undefined;
2670
2713
  }
2671
- return { data: allItems, stopReason: "maxPages", nextCursor: cursor };
2714
+ return {
2715
+ data: allItems,
2716
+ stopReason: "maxPages",
2717
+ ...position.offset === 0 && position.cursor !== undefined ? { nextCursor: position.cursor } : {},
2718
+ continuation
2719
+ };
2672
2720
  };
2673
2721
  // src/error-results.gen.ts
2674
2722
  var narrowError_addOrganizationMember = async (options) => callWithTypedErrors(() => addOrganizationMember({ ...options, responseStyle: "fields", throwOnError: false }), [401, 403, 404]);
@@ -4170,6 +4218,7 @@ export {
4170
4218
  createOrganizationDiscoverSavedQuery,
4171
4219
  createOrganizationDashboard,
4172
4220
  createOrganizationCodeMapping,
4221
+ consumePage,
4173
4222
  callWithTypedErrors,
4174
4223
  bulkUpsertOrganizationCodeMappings,
4175
4224
  assembleProjectDebugFiles,
@@ -19,12 +19,32 @@ export type PaginatedResponse<T> = {
19
19
  /** Cursor for the previous page. `undefined` on the first page. */
20
20
  prevCursor?: string;
21
21
  };
22
+ /** A position within a page fetched with an opaque server cursor. */
23
+ export type PagePosition = {
24
+ readonly cursor?: string;
25
+ /** Rows already consumed, before applying the next item budget. */
26
+ readonly offset: number;
27
+ };
28
+ /**
29
+ * Serializable continuation returned by `paginateUpTo`.
30
+ * Keep the same operation, query and fetcher configuration when resuming.
31
+ * Partial pages retain the fetcher's original request budget for exact replay;
32
+ * page boundaries use the next call's budget instead.
33
+ */
34
+ export type PaginationContinuation = PagePosition & ({
35
+ readonly offset: 0;
36
+ readonly requestBudget?: never;
37
+ } | {
38
+ readonly requestBudget: number;
39
+ });
22
40
  /** Aggregate data has no single HTTP response. Only `exhausted` means complete. */
23
41
  export type PaginatedCollection<TItem> = {
24
42
  data: Array<TItem>;
25
43
  stopReason: "exhausted" | "limit" | "maxPages";
26
44
  /** Omitted when exhausted or when trimming a page makes continuation unsafe. */
27
45
  nextCursor?: string;
46
+ /** `paginateUpTo` can resume here, including within a partially consumed page. */
47
+ continuation?: PaginationContinuation;
28
48
  };
29
49
  export type PaginateAllOptions = {
30
50
  /** Hard cap on the number of pages fetched. Default: 50. */
@@ -39,12 +59,42 @@ export type PaginateUpToOptions = {
39
59
  maxPages?: number;
40
60
  /** Resume forward traversal from a previous nextCursor, keeping the same query. */
41
61
  startCursor?: string;
62
+ /** Resume a batch, including pending rows in its last page. Cannot combine with startCursor. */
63
+ resume?: PaginationContinuation;
42
64
  /** Called after each page is fetched. Useful for progress indicators. */
43
65
  onPage?: (fetched: number, limit: number) => void;
44
66
  };
45
67
  export type PageFetcher<TData, TError> = (cursor: string | undefined) => Promise<SdkResult<TData, TError>>;
46
- /** The remaining item budget lets a custom fetcher reduce its HTTP page size. */
47
- export type BudgetedPageFetcher<TData, TError> = (cursor: string | undefined, remaining: number) => Promise<SdkResult<TData, TError>>;
68
+ /**
69
+ * The request budget lets a custom fetcher reduce its HTTP page size.
70
+ * Normally the remaining item budget; replaying a partial page repeats the
71
+ * original value even when the new batch has a different limit.
72
+ */
73
+ export type BudgetedPageFetcher<TData, TError> = (cursor: string | undefined, requestBudget: number) => Promise<SdkResult<TData, TError>>;
74
+ /** A page whose consumer already handled the HTTP response and any errors. */
75
+ export type CollectionPage<TItem> = {
76
+ data: Array<TItem>;
77
+ nextCursor?: string;
78
+ /** Reserved for SDK operation envelopes; normalized fetchers reject on failure. */
79
+ request?: never;
80
+ error?: never;
81
+ };
82
+ /** Compose an existing page fetcher with bounded collection, without HTTP objects. */
83
+ export type CollectionPageFetcher<TItem> = (cursor: string | undefined, requestBudget: number) => Promise<CollectionPage<TItem>>;
84
+ /**
85
+ * Consume rows from an already fetched page without fetching or interpreting cursors.
86
+ * Returns a position for the next consumption, or none when the page is fully
87
+ * consumed and the server advertises no next page. The caller retains the
88
+ * original response, headers and envelope; neither input is mutated.
89
+ *
90
+ * A position inside the current page requires fetching that page again with
91
+ * the same request options. An offset beyond a short page carries forward to
92
+ * its successor. Like server pagination, this does not snapshot changing data.
93
+ */
94
+ export declare function consumePage<T>(page: Pick<PaginatedResponse<Array<T>>, "data" | "nextCursor">, position: PagePosition, limit?: number): {
95
+ data: Array<T>;
96
+ position?: PagePosition;
97
+ };
48
98
  /**
49
99
  * Parse Sentry's Link header to extract pagination cursors.
50
100
  *
@@ -143,11 +193,12 @@ export declare const fetchPage: <TData, TError = unknown>(fetcher: PageFetcher<T
143
193
  */
144
194
  export declare const paginateAll: <TItem, TError = unknown>(fetcher: PageFetcher<Array<TItem>, TError>, context: string, options?: PaginateAllOptions) => Promise<PaginatedCollection<TItem>>;
145
195
  /**
146
- * Collect up to `limit` items, passing the remaining budget to the fetcher.
147
- * Generated wrappers use it to reduce supported HTTP page sizes.
196
+ * Collect up to `limit` items, passing a request budget to the fetcher.
197
+ * Generated wrappers use it to reduce supported HTTP page sizes. A partial
198
+ * continuation replays the original request budget before skipping consumed rows.
148
199
  *
149
200
  * If a server still returns more items than fit, trim the page and omit its
150
- * cursor: resuming past discarded items would skip records. Such a result
151
- * has `stopReason: "limit"`, even if the server has no further pages.
201
+ * server cursor: resuming past discarded items would skip records. The separate
202
+ * continuation preserves the pending rows, even if the server has no further pages.
152
203
  */
153
- export declare const paginateUpTo: <TItem, TError = unknown>(fetcher: BudgetedPageFetcher<Array<TItem>, TError>, options: PaginateUpToOptions, context: string) => Promise<PaginatedCollection<TItem>>;
204
+ export declare const paginateUpTo: <TItem, TError = unknown>(fetcher: BudgetedPageFetcher<Array<TItem>, TError> | CollectionPageFetcher<TItem>, options: PaginateUpToOptions, context: string) => Promise<PaginatedCollection<TItem>>;
@@ -0,0 +1,75 @@
1
+ /** Build-time analysis of API usage in consumer-supplied TypeScript source. */
2
+ import type { ApiOperation } from "./operation-types.js";
3
+ /** Identity supplied by the generated SDK operation catalog. */
4
+ export type SourceApiOperation = Pick<ApiOperation, "functionName" | "method" | "path">;
5
+ /** A consumer's raw request wrapper, identified by its resolved function name. */
6
+ export type SourceApiRequest = {
7
+ functionName: string;
8
+ /** Zero-based argument containing the request path. */
9
+ pathArgument: number;
10
+ /** Zero-based argument containing the options object. */
11
+ optionsArgument: number;
12
+ /** Options property containing query parameters. Defaults to `query`. */
13
+ queryProperty?: string;
14
+ /** Method when the options omit it. Defaults to GET; unknown spreads stay unknown. */
15
+ defaultMethod?: string;
16
+ };
17
+ /** Consumer conventions; none of these lists are inferred from command names. */
18
+ export type SourceApiAnalysisOptions = {
19
+ /** Factory names whose returned objects contain deferred callbacks. */
20
+ boundaries?: readonly string[];
21
+ /** Raw request wrappers to link to the operation catalog. */
22
+ requests?: readonly SourceApiRequest[];
23
+ /** Query keys to retain. The Sentry `query` key also retains fixed joined terms. */
24
+ queryParameters?: readonly string[];
25
+ /** Boolean property names to report when explicitly set to true. */
26
+ declarationFlags?: readonly string[];
27
+ };
28
+ /** An operation reachable from a source declaration. */
29
+ export type SourceOperationUsage = SourceApiOperation & {
30
+ /** Known query values or fixed terms; callers may add further filters. */
31
+ query?: Record<string, string>;
32
+ };
33
+ /** A raw request whose identity cannot be established from the public catalog. */
34
+ export type UnresolvedApiRequest = {
35
+ /** Source module, using the caller's source-map keys. */
36
+ file: string;
37
+ /** One-based request call line. */
38
+ line: number;
39
+ /** Known HTTP method, when statically available. */
40
+ method?: string;
41
+ /** Known path template, when statically available. */
42
+ path?: string;
43
+ /** Why no operation was selected. */
44
+ reason: string;
45
+ };
46
+ /** Source-derived relationships; no command is executed to obtain them. */
47
+ export type SourceApiUsage = {
48
+ /** Discovered API operations, preserving distinct contexts. */
49
+ operations: SourceOperationUsage[];
50
+ /** Reachable raw requests that need explicit discovery diagnostics. */
51
+ unresolvedRequests: UnresolvedApiRequest[];
52
+ /** Known HTTP methods, including unresolved requests and static method properties. */
53
+ methods: string[];
54
+ };
55
+ /** Source relationships and deferred callback boundaries; never executes input code. */
56
+ export type SourceApiAnalysis = {
57
+ /** Source file → exported symbol → reachable API usage. */
58
+ exports: Map<string, Map<string, SourceApiUsage>>;
59
+ /** Exported boundaries and their consumer-selected factory/flag evidence. */
60
+ boundaries: {
61
+ file: string;
62
+ name: string;
63
+ factories: string[];
64
+ flags: string[];
65
+ }[];
66
+ };
67
+ /**
68
+ * Follow function references, imports and barrel exports to SDK calls or known
69
+ * raw request wrappers. Dynamic paths remain diagnostics rather than guesses.
70
+ * Boundary factories have their arguments inspected, without traversing the
71
+ * factory's execution machinery. Reading their returned objects as data does
72
+ * not inherit callback usage. Results describe static reachability, not a
73
+ * complete execution trace; dynamic behavior may not be discoverable.
74
+ */
75
+ export declare function analyzeSourceApiUsage(sources: ReadonlyMap<string, string>, operations: readonly SourceApiOperation[], options?: SourceApiAnalysisOptions): SourceApiAnalysis;
@@ -0,0 +1,796 @@
1
+ // node:path
2
+ function assertPath(path) {
3
+ if (typeof path !== "string")
4
+ throw TypeError("Path must be a string. Received " + JSON.stringify(path));
5
+ }
6
+ function normalizeStringPosix(path, allowAboveRoot) {
7
+ var res = "", lastSegmentLength = 0, lastSlash = -1, dots = 0, code;
8
+ for (var i = 0;i <= path.length; ++i) {
9
+ if (i < path.length)
10
+ code = path.charCodeAt(i);
11
+ else if (code === 47)
12
+ break;
13
+ else
14
+ code = 47;
15
+ if (code === 47) {
16
+ if (lastSlash === i - 1 || dots === 1)
17
+ ;
18
+ else if (lastSlash !== i - 1 && dots === 2) {
19
+ if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 || res.charCodeAt(res.length - 2) !== 46) {
20
+ if (res.length > 2) {
21
+ var lastSlashIndex = res.lastIndexOf("/");
22
+ if (lastSlashIndex !== res.length - 1) {
23
+ if (lastSlashIndex === -1)
24
+ res = "", lastSegmentLength = 0;
25
+ else
26
+ res = res.slice(0, lastSlashIndex), lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
27
+ lastSlash = i, dots = 0;
28
+ continue;
29
+ }
30
+ } else if (res.length === 2 || res.length === 1) {
31
+ res = "", lastSegmentLength = 0, lastSlash = i, dots = 0;
32
+ continue;
33
+ }
34
+ }
35
+ if (allowAboveRoot) {
36
+ if (res.length > 0)
37
+ res += "/..";
38
+ else
39
+ res = "..";
40
+ lastSegmentLength = 2;
41
+ }
42
+ } else {
43
+ if (res.length > 0)
44
+ res += "/" + path.slice(lastSlash + 1, i);
45
+ else
46
+ res = path.slice(lastSlash + 1, i);
47
+ lastSegmentLength = i - lastSlash - 1;
48
+ }
49
+ lastSlash = i, dots = 0;
50
+ } else if (code === 46 && dots !== -1)
51
+ ++dots;
52
+ else
53
+ dots = -1;
54
+ }
55
+ return res;
56
+ }
57
+ function _format(sep, pathObject) {
58
+ var dir = pathObject.dir || pathObject.root, base = pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
59
+ if (!dir)
60
+ return base;
61
+ if (dir === pathObject.root)
62
+ return dir + base;
63
+ return dir + sep + base;
64
+ }
65
+ function resolve() {
66
+ var resolvedPath = "", resolvedAbsolute = false, cwd;
67
+ for (var i = arguments.length - 1;i >= -1 && !resolvedAbsolute; i--) {
68
+ var path;
69
+ if (i >= 0)
70
+ path = arguments[i];
71
+ else {
72
+ if (cwd === undefined)
73
+ cwd = process.cwd();
74
+ path = cwd;
75
+ }
76
+ if (assertPath(path), path.length === 0)
77
+ continue;
78
+ resolvedPath = path + "/" + resolvedPath, resolvedAbsolute = path.charCodeAt(0) === 47;
79
+ }
80
+ if (resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute), resolvedAbsolute)
81
+ if (resolvedPath.length > 0)
82
+ return "/" + resolvedPath;
83
+ else
84
+ return "/";
85
+ else if (resolvedPath.length > 0)
86
+ return resolvedPath;
87
+ else
88
+ return ".";
89
+ }
90
+ function normalize(path) {
91
+ if (assertPath(path), path.length === 0)
92
+ return ".";
93
+ var isAbsolute = path.charCodeAt(0) === 47, trailingSeparator = path.charCodeAt(path.length - 1) === 47;
94
+ if (path = normalizeStringPosix(path, !isAbsolute), path.length === 0 && !isAbsolute)
95
+ path = ".";
96
+ if (path.length > 0 && trailingSeparator)
97
+ path += "/";
98
+ if (isAbsolute)
99
+ return "/" + path;
100
+ return path;
101
+ }
102
+ function isAbsolute(path) {
103
+ return assertPath(path), path.length > 0 && path.charCodeAt(0) === 47;
104
+ }
105
+ function join() {
106
+ if (arguments.length === 0)
107
+ return ".";
108
+ var joined;
109
+ for (var i = 0;i < arguments.length; ++i) {
110
+ var arg = arguments[i];
111
+ if (assertPath(arg), arg.length > 0)
112
+ if (joined === undefined)
113
+ joined = arg;
114
+ else
115
+ joined += "/" + arg;
116
+ }
117
+ if (joined === undefined)
118
+ return ".";
119
+ return normalize(joined);
120
+ }
121
+ function relative(from, to) {
122
+ if (assertPath(from), assertPath(to), from === to)
123
+ return "";
124
+ if (from = resolve(from), to = resolve(to), from === to)
125
+ return "";
126
+ var fromStart = 1;
127
+ for (;fromStart < from.length; ++fromStart)
128
+ if (from.charCodeAt(fromStart) !== 47)
129
+ break;
130
+ var fromEnd = from.length, fromLen = fromEnd - fromStart, toStart = 1;
131
+ for (;toStart < to.length; ++toStart)
132
+ if (to.charCodeAt(toStart) !== 47)
133
+ break;
134
+ var toEnd = to.length, toLen = toEnd - toStart, length = fromLen < toLen ? fromLen : toLen, lastCommonSep = -1, i = 0;
135
+ for (;i <= length; ++i) {
136
+ if (i === length) {
137
+ if (toLen > length) {
138
+ if (to.charCodeAt(toStart + i) === 47)
139
+ return to.slice(toStart + i + 1);
140
+ else if (i === 0)
141
+ return to.slice(toStart + i);
142
+ } else if (fromLen > length) {
143
+ if (from.charCodeAt(fromStart + i) === 47)
144
+ lastCommonSep = i;
145
+ else if (i === 0)
146
+ lastCommonSep = 0;
147
+ }
148
+ break;
149
+ }
150
+ var fromCode = from.charCodeAt(fromStart + i), toCode = to.charCodeAt(toStart + i);
151
+ if (fromCode !== toCode)
152
+ break;
153
+ else if (fromCode === 47)
154
+ lastCommonSep = i;
155
+ }
156
+ var out = "";
157
+ for (i = fromStart + lastCommonSep + 1;i <= fromEnd; ++i)
158
+ if (i === fromEnd || from.charCodeAt(i) === 47)
159
+ if (out.length === 0)
160
+ out += "..";
161
+ else
162
+ out += "/..";
163
+ if (out.length > 0)
164
+ return out + to.slice(toStart + lastCommonSep);
165
+ else {
166
+ if (toStart += lastCommonSep, to.charCodeAt(toStart) === 47)
167
+ ++toStart;
168
+ return to.slice(toStart);
169
+ }
170
+ }
171
+ function _makeLong(path) {
172
+ return path;
173
+ }
174
+ function dirname(path) {
175
+ if (assertPath(path), path.length === 0)
176
+ return ".";
177
+ var code = path.charCodeAt(0), hasRoot = code === 47, end = -1, matchedSlash = true;
178
+ for (var i = path.length - 1;i >= 1; --i)
179
+ if (code = path.charCodeAt(i), code === 47) {
180
+ if (!matchedSlash) {
181
+ end = i;
182
+ break;
183
+ }
184
+ } else
185
+ matchedSlash = false;
186
+ if (end === -1)
187
+ return hasRoot ? "/" : ".";
188
+ if (hasRoot && end === 1)
189
+ return "//";
190
+ return path.slice(0, end);
191
+ }
192
+ function basename(path, ext) {
193
+ if (ext !== undefined && typeof ext !== "string")
194
+ throw TypeError('"ext" argument must be a string');
195
+ assertPath(path);
196
+ var start = 0, end = -1, matchedSlash = true, i;
197
+ if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
198
+ if (ext.length === path.length && ext === path)
199
+ return "";
200
+ var extIdx = ext.length - 1, firstNonSlashEnd = -1;
201
+ for (i = path.length - 1;i >= 0; --i) {
202
+ var code = path.charCodeAt(i);
203
+ if (code === 47) {
204
+ if (!matchedSlash) {
205
+ start = i + 1;
206
+ break;
207
+ }
208
+ } else {
209
+ if (firstNonSlashEnd === -1)
210
+ matchedSlash = false, firstNonSlashEnd = i + 1;
211
+ if (extIdx >= 0)
212
+ if (code === ext.charCodeAt(extIdx)) {
213
+ if (--extIdx === -1)
214
+ end = i;
215
+ } else
216
+ extIdx = -1, end = firstNonSlashEnd;
217
+ }
218
+ }
219
+ if (start === end)
220
+ end = firstNonSlashEnd;
221
+ else if (end === -1)
222
+ end = path.length;
223
+ return path.slice(start, end);
224
+ } else {
225
+ for (i = path.length - 1;i >= 0; --i)
226
+ if (path.charCodeAt(i) === 47) {
227
+ if (!matchedSlash) {
228
+ start = i + 1;
229
+ break;
230
+ }
231
+ } else if (end === -1)
232
+ matchedSlash = false, end = i + 1;
233
+ if (end === -1)
234
+ return "";
235
+ return path.slice(start, end);
236
+ }
237
+ }
238
+ function extname(path) {
239
+ assertPath(path);
240
+ var startDot = -1, startPart = 0, end = -1, matchedSlash = true, preDotState = 0;
241
+ for (var i = path.length - 1;i >= 0; --i) {
242
+ var code = path.charCodeAt(i);
243
+ if (code === 47) {
244
+ if (!matchedSlash) {
245
+ startPart = i + 1;
246
+ break;
247
+ }
248
+ continue;
249
+ }
250
+ if (end === -1)
251
+ matchedSlash = false, end = i + 1;
252
+ if (code === 46) {
253
+ if (startDot === -1)
254
+ startDot = i;
255
+ else if (preDotState !== 1)
256
+ preDotState = 1;
257
+ } else if (startDot !== -1)
258
+ preDotState = -1;
259
+ }
260
+ if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)
261
+ return "";
262
+ return path.slice(startDot, end);
263
+ }
264
+ function format(pathObject) {
265
+ if (pathObject === null || typeof pathObject !== "object")
266
+ throw TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
267
+ return _format("/", pathObject);
268
+ }
269
+ function parse(path) {
270
+ assertPath(path);
271
+ var ret = { root: "", dir: "", base: "", ext: "", name: "" };
272
+ if (path.length === 0)
273
+ return ret;
274
+ var code = path.charCodeAt(0), isAbsolute2 = code === 47, start;
275
+ if (isAbsolute2)
276
+ ret.root = "/", start = 1;
277
+ else
278
+ start = 0;
279
+ var startDot = -1, startPart = 0, end = -1, matchedSlash = true, i = path.length - 1, preDotState = 0;
280
+ for (;i >= start; --i) {
281
+ if (code = path.charCodeAt(i), code === 47) {
282
+ if (!matchedSlash) {
283
+ startPart = i + 1;
284
+ break;
285
+ }
286
+ continue;
287
+ }
288
+ if (end === -1)
289
+ matchedSlash = false, end = i + 1;
290
+ if (code === 46) {
291
+ if (startDot === -1)
292
+ startDot = i;
293
+ else if (preDotState !== 1)
294
+ preDotState = 1;
295
+ } else if (startDot !== -1)
296
+ preDotState = -1;
297
+ }
298
+ if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
299
+ if (end !== -1)
300
+ if (startPart === 0 && isAbsolute2)
301
+ ret.base = ret.name = path.slice(1, end);
302
+ else
303
+ ret.base = ret.name = path.slice(startPart, end);
304
+ } else {
305
+ if (startPart === 0 && isAbsolute2)
306
+ ret.name = path.slice(1, startDot), ret.base = path.slice(1, end);
307
+ else
308
+ ret.name = path.slice(startPart, startDot), ret.base = path.slice(startPart, end);
309
+ ret.ext = path.slice(startDot, end);
310
+ }
311
+ if (startPart > 0)
312
+ ret.dir = path.slice(0, startPart - 1);
313
+ else if (isAbsolute2)
314
+ ret.dir = "/";
315
+ return ret;
316
+ }
317
+ var sep = "/";
318
+ var delimiter = ":";
319
+ var posix = ((p) => (p.posix = p, p))({ resolve, normalize, isAbsolute, join, relative, _makeLong, dirname, basename, extname, format, parse, sep, delimiter, win32: null, posix: null });
320
+
321
+ // src/source-analysis.ts
322
+ import ts from "typescript";
323
+ var SDK = "@sentry/api";
324
+ var API_PREFIX = /^\/api\/\d+(?=\/)/;
325
+ var PATH_PARAMETER = /\{[^}]*\}/g;
326
+ function unwrap(node) {
327
+ return ts.isAsExpression(node) || ts.isSatisfiesExpression(node) || ts.isParenthesizedExpression(node) || ts.isNonNullExpression(node) ? unwrap(node.expression) : node;
328
+ }
329
+ function bindsName(binding, name) {
330
+ return ts.isIdentifier(binding) ? binding.text === name : binding.elements.some((element) => ts.isBindingElement(element) && bindsName(element.name, name));
331
+ }
332
+ function lexicalDeclaration(node, includeSource = false) {
333
+ for (let parent = node.parent;parent && (includeSource || !ts.isSourceFile(parent)); parent = parent.parent) {
334
+ if (ts.isFunctionLike(parent)) {
335
+ const parameter = parent.parameters.find((parameter2) => bindsName(parameter2.name, node.text));
336
+ if (parameter)
337
+ return parameter;
338
+ }
339
+ if ((ts.isFunctionExpression(parent) || ts.isClassExpression(parent)) && parent.name?.text === node.text)
340
+ return parent;
341
+ if (ts.isCatchClause(parent) && parent.variableDeclaration && bindsName(parent.variableDeclaration.name, node.text))
342
+ return parent.variableDeclaration;
343
+ if ((ts.isForStatement(parent) || ts.isForOfStatement(parent) || ts.isForInStatement(parent)) && parent.initializer && ts.isVariableDeclarationList(parent.initializer)) {
344
+ const declaration = parent.initializer.declarations.find((declaration2) => bindsName(declaration2.name, node.text));
345
+ if (declaration)
346
+ return declaration;
347
+ }
348
+ if (ts.isBlock(parent) || ts.isSourceFile(parent)) {
349
+ for (const statement of parent.statements) {
350
+ if (ts.isVariableStatement(statement)) {
351
+ const declaration = statement.declarationList.declarations.find((declaration2) => bindsName(declaration2.name, node.text));
352
+ if (declaration)
353
+ return declaration;
354
+ }
355
+ if ((ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name?.text === node.text)
356
+ return statement;
357
+ }
358
+ }
359
+ }
360
+ return;
361
+ }
362
+ function sourceModule(file, specifier, sources) {
363
+ if (!specifier.startsWith("."))
364
+ return specifier;
365
+ const target = posix.normalize(posix.join(dirname(file), specifier));
366
+ const extension = posix.extname(target);
367
+ const candidates = extension === ".js" ? [target.replace(/\.js$/, ".ts"), target.replace(/\.js$/, ".tsx"), target] : extension ? [target] : [target, `${target}.ts`, `${target}.tsx`, posix.join(target, "index.ts"), posix.join(target, "index.tsx")];
368
+ return candidates.find((candidate) => sources.has(candidate)) ?? target;
369
+ }
370
+ function parseModule(file, text, sources) {
371
+ const source = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true);
372
+ const mod = {
373
+ source,
374
+ imports: new Map,
375
+ exports: new Map,
376
+ stars: [],
377
+ declarations: new Map
378
+ };
379
+ for (const statement of source.statements) {
380
+ if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
381
+ if (statement.importClause?.isTypeOnly)
382
+ continue;
383
+ const target = sourceModule(file, statement.moduleSpecifier.text, sources);
384
+ const defaultImport = statement.importClause?.name;
385
+ if (defaultImport)
386
+ mod.imports.set(defaultImport.text, { file: target, name: "default" });
387
+ const bindings = statement.importClause?.namedBindings;
388
+ if (bindings && ts.isNamedImports(bindings)) {
389
+ for (const binding of bindings.elements) {
390
+ if (!binding.isTypeOnly)
391
+ mod.imports.set(binding.name.text, {
392
+ file: target,
393
+ name: (binding.propertyName ?? binding.name).text
394
+ });
395
+ }
396
+ } else if (bindings && ts.isNamespaceImport(bindings)) {
397
+ mod.imports.set(bindings.name.text, { file: target, name: "*" });
398
+ }
399
+ continue;
400
+ }
401
+ if (ts.isExportDeclaration(statement) && !statement.isTypeOnly) {
402
+ const target = statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier) ? sourceModule(file, statement.moduleSpecifier.text, sources) : file;
403
+ if (!statement.exportClause)
404
+ mod.stars.push(target);
405
+ else if (ts.isNamedExports(statement.exportClause)) {
406
+ for (const binding of statement.exportClause.elements) {
407
+ if (!binding.isTypeOnly)
408
+ mod.exports.set(binding.name.text, {
409
+ file: target,
410
+ name: (binding.propertyName ?? binding.name).text
411
+ });
412
+ }
413
+ }
414
+ continue;
415
+ }
416
+ const modifiers = ts.canHaveModifiers(statement) ? ts.getModifiers(statement) : undefined;
417
+ const isDefault = modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.DefaultKeyword) || ts.isExportAssignment(statement) && !statement.isExportEquals;
418
+ const nodes = [];
419
+ if (ts.isFunctionDeclaration(statement) && statement.body && (statement.name || isDefault))
420
+ nodes.push([statement.name?.text ?? "default", statement]);
421
+ if (ts.isExportAssignment(statement) && !statement.isExportEquals)
422
+ nodes.push(["default", statement.expression]);
423
+ if (ts.isVariableStatement(statement)) {
424
+ for (const declaration of statement.declarationList.declarations) {
425
+ if (ts.isIdentifier(declaration.name) && declaration.initializer)
426
+ nodes.push([declaration.name.text, declaration.initializer]);
427
+ }
428
+ }
429
+ for (const [name, node] of nodes) {
430
+ mod.declarations.set(name, {
431
+ node,
432
+ refs: new Set,
433
+ calls: new Set,
434
+ usage: { operations: [], unresolvedRequests: [], methods: [] },
435
+ boundary: false,
436
+ factories: new Set,
437
+ flags: new Set
438
+ });
439
+ if (isDefault)
440
+ mod.exports.set("default", { file, name });
441
+ else if (modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword))
442
+ mod.exports.set(name, { file, name });
443
+ }
444
+ }
445
+ return mod;
446
+ }
447
+ function analyzeSourceApiUsage(sources, operations, options = {}) {
448
+ const boundaries = new Set(options.boundaries);
449
+ const requests = new Map(options.requests?.map((request) => [request.functionName, request]));
450
+ const declarationFlags = new Set(options.declarationFlags);
451
+ const modules = new Map([...sources].map(([file, text]) => [
452
+ file,
453
+ parseModule(file, text, sources)
454
+ ]));
455
+ const sdk = new Map(operations.map((operation) => [operation.functionName, operation]));
456
+ const identities = new Map;
457
+ const pathKey = (path) => `/${path.replace(API_PREFIX, "").split("/").filter(Boolean).join("/")}/`.replace(PATH_PARAMETER, "{}");
458
+ for (const operation of operations) {
459
+ const key = `${operation.method}:${pathKey(operation.path)}`;
460
+ identities.set(key, [...identities.get(key) ?? [], operation]);
461
+ }
462
+ function resolve2(binding, exported = false, seen = new Set) {
463
+ if (binding.file === SDK)
464
+ return binding;
465
+ const key = `${binding.file}#${binding.name}#${exported}`;
466
+ if (seen.has(key))
467
+ return;
468
+ seen.add(key);
469
+ const mod = modules.get(binding.file);
470
+ if (!mod)
471
+ return;
472
+ if (!exported) {
473
+ if (mod.declarations.has(binding.name))
474
+ return binding;
475
+ const imported = mod.imports.get(binding.name);
476
+ return imported ? resolve2(imported, true, seen) : undefined;
477
+ }
478
+ const next = mod.exports.get(binding.name);
479
+ if (next)
480
+ return resolve2(next, next.file !== binding.file, seen);
481
+ if (binding.name === "default")
482
+ return;
483
+ for (const target of mod.stars) {
484
+ const found = resolve2({ file: target, name: binding.name }, true, seen);
485
+ if (found)
486
+ return found;
487
+ }
488
+ return;
489
+ }
490
+ function bindingFor(file, node) {
491
+ const mod = modules.get(file);
492
+ if (ts.isIdentifier(node)) {
493
+ if (lexicalDeclaration(node))
494
+ return;
495
+ const imported = mod.imports.get(node.text);
496
+ return imported ? resolve2(imported, true) ?? (!modules.has(imported.file) ? imported : undefined) : resolve2({ file, name: node.text });
497
+ }
498
+ if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && !lexicalDeclaration(node.expression)) {
499
+ const namespace = mod.imports.get(node.expression.text);
500
+ if (namespace?.name === "*")
501
+ return resolve2({ file: namespace.file, name: node.name.text }, true);
502
+ }
503
+ return;
504
+ }
505
+ function callableBinding(binding) {
506
+ const seen = new Set;
507
+ while (binding?.name === "default") {
508
+ const key = `${binding.file}#${binding.name}`;
509
+ if (seen.has(key))
510
+ break;
511
+ seen.add(key);
512
+ const declaration = modules.get(binding.file)?.declarations.get(binding.name);
513
+ if (!declaration)
514
+ break;
515
+ const node = unwrap(declaration.node);
516
+ if (!ts.isIdentifier(node))
517
+ break;
518
+ const target = bindingFor(binding.file, node);
519
+ if (!target)
520
+ break;
521
+ binding = target;
522
+ }
523
+ return binding;
524
+ }
525
+ function initializer(node) {
526
+ if (!ts.isIdentifier(node))
527
+ return;
528
+ const declaration = lexicalDeclaration(node, true);
529
+ return declaration && ts.isVariableDeclaration(declaration) && ts.isIdentifier(declaration.name) && ts.isVariableDeclarationList(declaration.parent) && declaration.parent.flags & ts.NodeFlags.Const ? declaration.initializer : undefined;
530
+ }
531
+ function value(node, template = false, seen = new Set) {
532
+ if (!node || seen.has(node))
533
+ return;
534
+ seen.add(node);
535
+ node = unwrap(node);
536
+ if (ts.isStringLiteralLike(node) || ts.isNumericLiteral(node))
537
+ return node.text;
538
+ if (node.kind === ts.SyntaxKind.TrueKeyword)
539
+ return "true";
540
+ if (node.kind === ts.SyntaxKind.FalseKeyword)
541
+ return "false";
542
+ if (ts.isIdentifier(node))
543
+ return value(initializer(node), template, seen);
544
+ if (ts.isTemplateExpression(node)) {
545
+ let result2 = node.head.text;
546
+ for (const span of node.templateSpans) {
547
+ const part = value(span.expression, false, new Set(seen));
548
+ if (part === undefined && !template)
549
+ return;
550
+ result2 += (part ?? "{}") + span.literal.text;
551
+ }
552
+ return result2;
553
+ }
554
+ return;
555
+ }
556
+ function property(node, name, seen = new Set) {
557
+ if (node == null)
558
+ return node;
559
+ if (seen.has(node))
560
+ return null;
561
+ seen.add(node);
562
+ node = unwrap(node);
563
+ if (ts.isIdentifier(node)) {
564
+ const initial = initializer(node);
565
+ return initial ? property(initial, name, seen) : null;
566
+ }
567
+ if (!ts.isObjectLiteralExpression(node))
568
+ return null;
569
+ for (const member of [...node.properties].reverse()) {
570
+ if (ts.isSpreadAssignment(member)) {
571
+ const found = property(member.expression, name, new Set(seen));
572
+ if (found !== undefined)
573
+ return found;
574
+ continue;
575
+ }
576
+ const key = ts.isComputedPropertyName(member.name) ? value(member.name.expression) : member.name.text;
577
+ if (key === undefined)
578
+ return null;
579
+ if (key !== name)
580
+ continue;
581
+ if (ts.isPropertyAssignment(member))
582
+ return member.initializer;
583
+ if (ts.isShorthandPropertyAssignment(member))
584
+ return member.name;
585
+ return null;
586
+ }
587
+ return;
588
+ }
589
+ function queryTerms(node, seen = new Set) {
590
+ if (!node || seen.has(node))
591
+ return;
592
+ const exact = value(node);
593
+ if (exact !== undefined)
594
+ return exact;
595
+ seen.add(node);
596
+ node = unwrap(node);
597
+ if (ts.isIdentifier(node))
598
+ return queryTerms(initializer(node), seen);
599
+ if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.BarBarToken)
600
+ return queryTerms(node.left, seen);
601
+ if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression) || node.expression.name.text !== "join" || value(node.arguments[0]) !== " ")
602
+ return;
603
+ let array = node.expression.expression;
604
+ if (ts.isCallExpression(array) && ts.isPropertyAccessExpression(array.expression) && array.expression.name.text === "filter" && array.arguments[0]?.getText() === "Boolean")
605
+ array = array.expression.expression;
606
+ if (!ts.isArrayLiteralExpression(array))
607
+ return;
608
+ const terms = array.elements.map((item) => value(item)).filter((term) => !!term);
609
+ return terms.length ? terms.join(" ") : undefined;
610
+ }
611
+ function queryContext(requestOptions, key) {
612
+ const query = property(requestOptions, key);
613
+ const result2 = {};
614
+ for (const name of options.queryParameters ?? []) {
615
+ const expression = property(query, name);
616
+ const text = name === "query" ? queryTerms(expression) : value(expression);
617
+ if (text)
618
+ result2[name] = text;
619
+ }
620
+ return Object.keys(result2).length ? result2 : undefined;
621
+ }
622
+ for (const [file, mod] of modules) {
623
+ for (const declaration of mod.declarations.values()) {
624
+ let visit = function(node) {
625
+ if (ts.isTypeNode(node))
626
+ return;
627
+ if (ts.isPropertyAssignment(node) && declarationFlags.has(node.name.getText()) && node.initializer.kind === ts.SyntaxKind.TrueKeyword && property(node.parent, node.name.getText()) === node.initializer)
628
+ declaration.flags.add(node.name.getText());
629
+ if (ts.isPropertyAssignment(node) && node.name.getText() === "method") {
630
+ const method = value(node.initializer);
631
+ if (method)
632
+ declaration.usage.methods.push(method.toUpperCase());
633
+ }
634
+ if (ts.isCallExpression(node)) {
635
+ const reference = bindingFor(file, node.expression);
636
+ if (reference)
637
+ declaration.calls.add(`${reference.file}#${reference.name}`);
638
+ const binding = callableBinding(reference);
639
+ const name = binding?.name ?? (ts.isIdentifier(node.expression) && !lexicalDeclaration(node.expression) ? node.expression.text : "");
640
+ if (boundaries.has(name)) {
641
+ declaration.boundary = true;
642
+ declaration.factories.add(name);
643
+ for (const argument of node.arguments)
644
+ visit(argument);
645
+ return;
646
+ }
647
+ const operation = binding?.file === SDK ? sdk.get(name) : undefined;
648
+ if (operation) {
649
+ declaration.usage.operations.push({
650
+ ...operation,
651
+ query: queryContext(node.arguments[0], "query")
652
+ });
653
+ declaration.usage.methods.push(operation.method);
654
+ for (const argument of node.arguments)
655
+ visit(argument);
656
+ return;
657
+ }
658
+ const request = requests.get(name);
659
+ if (request) {
660
+ const requestOptions = node.arguments[request.optionsArgument];
661
+ const methodExpression = property(requestOptions, "method");
662
+ const method = methodExpression === undefined ? (request.defaultMethod ?? "GET").toUpperCase() : value(methodExpression)?.toUpperCase();
663
+ const path = value(node.arguments[request.pathArgument], true);
664
+ const matches = method && path ? identities.get(`${method}:${pathKey(path)}`) ?? [] : [];
665
+ if (method)
666
+ declaration.usage.methods.push(method);
667
+ if (matches.length === 1)
668
+ declaration.usage.operations.push({
669
+ ...matches[0],
670
+ query: queryContext(requestOptions, request.queryProperty ?? "query")
671
+ });
672
+ else
673
+ declaration.usage.unresolvedRequests.push({
674
+ file,
675
+ line: mod.source.getLineAndCharacterOfPosition(node.getStart()).line + 1,
676
+ method,
677
+ path,
678
+ reason: !method || !path ? "Dynamic request identity" : matches.length ? "Ambiguous catalog path" : "Request is not in the public catalog"
679
+ });
680
+ for (const argument of node.arguments)
681
+ visit(argument);
682
+ return;
683
+ }
684
+ }
685
+ if (ts.isIdentifier(node) || ts.isPropertyAccessExpression(node)) {
686
+ const parent = node.parent;
687
+ const isName = ts.isPropertyAccessExpression(parent) && parent.name === node || (ts.isPropertyAssignment(parent) || ts.isMethodDeclaration(parent) || ts.isVariableDeclaration(parent) || ts.isParameter(parent) || ts.isFunctionDeclaration(parent)) && parent.name === node;
688
+ if (!isName) {
689
+ const binding = bindingFor(file, node);
690
+ if (binding && !boundaries.has(binding.name)) {
691
+ const operation = binding.file === SDK ? sdk.get(binding.name) : undefined;
692
+ if (operation) {
693
+ declaration.usage.operations.push(operation);
694
+ declaration.usage.methods.push(operation.method);
695
+ } else
696
+ declaration.refs.add(`${binding.file}#${binding.name}`);
697
+ }
698
+ }
699
+ }
700
+ node.forEachChild(visit);
701
+ };
702
+ visit(declaration.node);
703
+ }
704
+ }
705
+ const declarations = new Map([...modules].flatMap(([file, mod]) => [...mod.declarations].map(([name, declaration]) => [`${file}#${name}`, declaration])));
706
+ function unique(items) {
707
+ return [
708
+ ...new Map(items.map((item) => [JSON.stringify(item), item])).values()
709
+ ];
710
+ }
711
+ function isAlias(declaration, ref) {
712
+ const node = unwrap(declaration.node);
713
+ if (!ts.isIdentifier(node) && !ts.isPropertyAccessExpression(node))
714
+ return false;
715
+ const binding = bindingFor(node.getSourceFile().fileName, node);
716
+ return !!binding && `${binding.file}#${binding.name}` === ref;
717
+ }
718
+ let changed = true;
719
+ while (changed) {
720
+ changed = false;
721
+ for (const declaration of declarations.values()) {
722
+ for (const ref of declaration.refs) {
723
+ const child = declarations.get(ref);
724
+ if (!child?.boundary || !declaration.calls.has(ref) && !isAlias(declaration, ref))
725
+ continue;
726
+ if (!declaration.boundary)
727
+ changed = true;
728
+ declaration.boundary = true;
729
+ for (const factory of child.factories) {
730
+ if (!declaration.factories.has(factory))
731
+ changed = true;
732
+ declaration.factories.add(factory);
733
+ }
734
+ for (const flag of child.flags) {
735
+ if (!declaration.flags.has(flag))
736
+ changed = true;
737
+ declaration.flags.add(flag);
738
+ }
739
+ }
740
+ }
741
+ }
742
+ changed = true;
743
+ while (changed) {
744
+ changed = false;
745
+ for (const declaration of declarations.values()) {
746
+ const before = JSON.stringify(declaration.usage);
747
+ for (const ref of declaration.refs) {
748
+ const child = declarations.get(ref);
749
+ if (!child)
750
+ continue;
751
+ if (child.boundary && !ts.isFunctionLike(unwrap(child.node)) && !isAlias(declaration, ref))
752
+ continue;
753
+ declaration.usage.operations.push(...child.usage.operations);
754
+ declaration.usage.unresolvedRequests.push(...child.usage.unresolvedRequests);
755
+ declaration.usage.methods.push(...child.usage.methods);
756
+ }
757
+ declaration.usage.operations = unique(declaration.usage.operations);
758
+ declaration.usage.unresolvedRequests = unique(declaration.usage.unresolvedRequests);
759
+ declaration.usage.methods = unique(declaration.usage.methods);
760
+ changed ||= before !== JSON.stringify(declaration.usage);
761
+ }
762
+ }
763
+ const result = { exports: new Map, boundaries: [] };
764
+ function exportNames(file, seen = new Set) {
765
+ if (seen.has(file))
766
+ return [];
767
+ seen.add(file);
768
+ const mod = modules.get(file);
769
+ return mod ? [
770
+ ...mod.exports.keys(),
771
+ ...mod.stars.flatMap((target) => exportNames(target, seen).filter((name) => name !== "default"))
772
+ ] : [];
773
+ }
774
+ for (const file of modules.keys()) {
775
+ const exported = new Map;
776
+ for (const name of new Set(exportNames(file))) {
777
+ const binding = resolve2({ file, name }, true);
778
+ const declaration = binding && declarations.get(`${binding.file}#${binding.name}`);
779
+ if (!declaration)
780
+ continue;
781
+ exported.set(name, declaration.usage);
782
+ if (declaration.boundary)
783
+ result.boundaries.push({
784
+ file,
785
+ name,
786
+ factories: [...declaration.factories],
787
+ flags: [...declaration.flags]
788
+ });
789
+ }
790
+ result.exports.set(file, exported);
791
+ }
792
+ return result;
793
+ }
794
+ export {
795
+ analyzeSourceApiUsage
796
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/api",
3
- "version": "0.423.0",
3
+ "version": "0.425.0",
4
4
  "description": "Official auto-generated TypeScript client for the Sentry public REST API",
5
5
  "keywords": [
6
6
  "sentry",
@@ -42,6 +42,10 @@
42
42
  "./operations": {
43
43
  "types": "./dist/operations.d.ts",
44
44
  "import": "./dist/operations.js"
45
+ },
46
+ "./source-analysis": {
47
+ "types": "./dist/source-analysis.d.ts",
48
+ "import": "./dist/source-analysis.js"
45
49
  }
46
50
  },
47
51
  "homepage": "https://docs.sentry.io/api/",
@@ -56,10 +60,14 @@
56
60
  "url": "https://github.com/getsentry/sentry-api-schema/issues"
57
61
  },
58
62
  "peerDependencies": {
63
+ "typescript": "*",
59
64
  "valibot": "*",
60
65
  "zod": "^3.24.0"
61
66
  },
62
67
  "peerDependenciesMeta": {
68
+ "typescript": {
69
+ "optional": true
70
+ },
63
71
  "valibot": {
64
72
  "optional": true
65
73
  },