@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 +92 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +60 -11
- package/dist/sentry-pagination.d.ts +58 -7
- package/dist/source-analysis.d.ts +75 -0
- package/dist/source-analysis.js +796 -0
- package/package.json +9 -1
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
|
|
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
|
|
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
|
|
2657
|
-
const
|
|
2658
|
-
|
|
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 (
|
|
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 {
|
|
2705
|
+
return {
|
|
2706
|
+
data: allItems,
|
|
2707
|
+
stopReason: "limit",
|
|
2708
|
+
...position.offset === 0 && position.cursor !== undefined ? { nextCursor: position.cursor } : {},
|
|
2709
|
+
continuation
|
|
2710
|
+
};
|
|
2668
2711
|
}
|
|
2669
|
-
|
|
2712
|
+
replayBudget = position.offset > 0 ? requestBudget : undefined;
|
|
2670
2713
|
}
|
|
2671
|
-
return {
|
|
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
|
-
/**
|
|
47
|
-
|
|
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
|
|
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.
|
|
151
|
-
*
|
|
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.
|
|
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
|
},
|