index.tsx 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245
  1. // XXX(epurkhiser): When we switch to the new React JSX runtime we will no
  2. // longer need this import and can drop babel-preset-css-prop for babel-preset.
  3. /// <reference types="@emotion/react/types/css-prop" />
  4. import {FocusTrap} from 'focus-trap';
  5. import u2f from 'u2f-api';
  6. import exportGlobals from 'app/bootstrap/exportGlobals';
  7. import Alert from 'app/components/alert';
  8. import {getInterval} from 'app/components/charts/utils';
  9. import {SymbolicatorStatus} from 'app/components/events/interfaces/types';
  10. import {API_ACCESS_SCOPES, DEFAULT_RELATIVE_PERIODS} from 'app/constants';
  11. import {PlatformKey} from 'app/data/platformCategories';
  12. import {OrgExperiments, UserExperiments} from 'app/types/experiments';
  13. import {
  14. INSTALLED,
  15. NOT_INSTALLED,
  16. PENDING,
  17. } from 'app/views/organizationIntegrations/constants';
  18. import {Field} from 'app/views/settings/components/forms/type';
  19. import {DynamicSamplingRules} from './dynamicSampling';
  20. import {Event} from './event';
  21. import {Mechanism, RawStacktrace, StacktraceType} from './stacktrace';
  22. export enum SentryInitRenderReactComponent {
  23. INDICATORS = 'Indicators',
  24. SETUP_WIZARD = 'SetupWizard',
  25. SYSTEM_ALERTS = 'SystemAlerts',
  26. U2F_SIGN = 'U2fSign',
  27. }
  28. export type OnSentryInitConfiguration =
  29. | {
  30. name: 'passwordStrength';
  31. input: string;
  32. element: string;
  33. }
  34. | {
  35. name: 'renderReact';
  36. container: string;
  37. component: SentryInitRenderReactComponent;
  38. props?: Record<string, any>;
  39. }
  40. | {
  41. name: 'onReady';
  42. onReady: (globals: typeof exportGlobals) => void;
  43. };
  44. declare global {
  45. interface Window {
  46. /**
  47. * Assets public location
  48. */
  49. __sentryGlobalStaticPrefix: string;
  50. /**
  51. * The config object provided by the backend.
  52. */
  53. __initialData: Config;
  54. /**
  55. * Pipeline
  56. */
  57. __pipelineInitialData: PipelineInitialData;
  58. /**
  59. * This allows our server-rendered templates to push configuration that should be
  60. * run after we render our main application.
  61. *
  62. * An example of this is dynamically importing the `passwordStrength` module only
  63. * on the organization login page.
  64. */
  65. __onSentryInit:
  66. | OnSentryInitConfiguration[]
  67. | {
  68. push: (config: OnSentryInitConfiguration) => void;
  69. };
  70. /**
  71. * Sentrys version string
  72. */
  73. __SENTRY__VERSION?: string;
  74. /**
  75. * The CSRF cookie ised on the backend
  76. */
  77. csrfCookieName?: string;
  78. /**
  79. * Used to open tooltips for testing purposes.
  80. */
  81. __openAllTooltips: () => void;
  82. /**
  83. * Used to close tooltips for testing purposes.
  84. */
  85. __closeAllTooltips: () => void;
  86. /**
  87. * Primary entrypoint for rendering the sentry app. This is typically
  88. * called in the django templates, or in the case of the EXPERIMENTAL_SPA,
  89. * after config hydration.
  90. */
  91. SentryRenderApp: () => void;
  92. sentryEmbedCallback?: ((embed: any) => void) | null;
  93. /**
  94. * Set to true if adblock could be installed.
  95. * See sentry/js/ads.js for how this global is disabled.
  96. */
  97. adblockSuspected?: boolean;
  98. // typing currently used for demo add on
  99. // TODO: improve typing
  100. SentryApp?: {
  101. HookStore: any;
  102. ConfigStore: any;
  103. Modal: any;
  104. modalFocusTrap?: {
  105. current?: FocusTrap;
  106. };
  107. getModalPortal: () => HTMLElement;
  108. };
  109. }
  110. }
  111. export type PipelineInitialData = {
  112. name: string;
  113. props: Record<string, any>;
  114. };
  115. export type IntegrationInstallationStatus =
  116. | typeof INSTALLED
  117. | typeof NOT_INSTALLED
  118. | typeof PENDING;
  119. export type SentryAppStatus = 'unpublished' | 'published' | 'internal';
  120. export type ObjectStatus =
  121. | 'active'
  122. | 'disabled'
  123. | 'pending_deletion'
  124. | 'deletion_in_progress';
  125. export type Avatar = {
  126. avatarUuid: string | null;
  127. avatarType: 'letter_avatar' | 'upload' | 'gravatar' | 'background';
  128. };
  129. export type Actor = {
  130. type: 'user' | 'team';
  131. id: string;
  132. name: string;
  133. email?: string;
  134. };
  135. /**
  136. * Organization summaries are sent when you request a
  137. * list of all organizations
  138. */
  139. export type OrganizationSummary = {
  140. status: {
  141. // TODO(ts): Are these fields == `ObjectStatus`?
  142. id: string;
  143. name: string;
  144. };
  145. require2FA: boolean;
  146. avatar: Avatar;
  147. features: string[];
  148. name: string;
  149. dateCreated: string;
  150. id: string;
  151. isEarlyAdopter: boolean;
  152. slug: string;
  153. };
  154. export type Relay = {
  155. publicKey: string;
  156. name: string;
  157. created?: string;
  158. lastModified?: string;
  159. description?: string;
  160. };
  161. export type RelayActivity = {
  162. publicKey: string;
  163. relayId: string;
  164. version: string;
  165. firstSeen: string;
  166. lastSeen: string;
  167. };
  168. export type RelaysByPublickey = {
  169. [publicKey: string]: {
  170. name: string;
  171. activities: Array<RelayActivity>;
  172. description?: string;
  173. created?: string;
  174. };
  175. };
  176. /**
  177. * Detailed organization (e.g. when requesting details for a single org)
  178. *
  179. * Lightweight in this case means it does not contain `projects` or `teams`
  180. */
  181. export type LightWeightOrganization = OrganizationSummary & {
  182. relayPiiConfig: string;
  183. scrubIPAddresses: boolean;
  184. attachmentsRole: string;
  185. debugFilesRole: string;
  186. eventsMemberAdmin: boolean;
  187. alertsMemberWrite: boolean;
  188. sensitiveFields: string[];
  189. openMembership: boolean;
  190. quota: {
  191. maxRateInterval: number | null;
  192. projectLimit: number | null;
  193. accountLimit: number | null;
  194. maxRate: number | null;
  195. };
  196. defaultRole: string;
  197. experiments: Partial<OrgExperiments>;
  198. allowJoinRequests: boolean;
  199. scrapeJavaScript: boolean;
  200. isDefault: boolean;
  201. pendingAccessRequests: number;
  202. availableRoles: {id: string; name: string}[];
  203. enhancedPrivacy: boolean;
  204. safeFields: string[];
  205. storeCrashReports: number;
  206. access: Scope[];
  207. allowSharedIssues: boolean;
  208. dataScrubberDefaults: boolean;
  209. dataScrubber: boolean;
  210. apdexThreshold: number;
  211. onboardingTasks: OnboardingTaskStatus[];
  212. trustedRelays: Relay[];
  213. role?: string;
  214. };
  215. /**
  216. * Full organization details
  217. */
  218. export type Organization = LightWeightOrganization & {
  219. projects: Project[];
  220. };
  221. /**
  222. * Minimal organization shape used on shared issue views.
  223. */
  224. export type SharedViewOrganization = {
  225. slug: string;
  226. id?: string;
  227. features?: Array<string>;
  228. };
  229. // Minimal project representation for use with avatars.
  230. export type AvatarProject = {
  231. slug: string;
  232. platform?: PlatformKey;
  233. id?: string | number;
  234. };
  235. /**
  236. * Simple timeseries data used in groups, projects and release health.
  237. */
  238. export type TimeseriesValue = [timestamp: number, value: number];
  239. export type Project = {
  240. id: string;
  241. dateCreated: string;
  242. isMember: boolean;
  243. teams: Team[];
  244. features: string[];
  245. organization: Organization;
  246. isBookmarked: boolean;
  247. isInternal: boolean;
  248. hasUserReports?: boolean;
  249. hasAccess: boolean;
  250. hasSessions: boolean;
  251. firstEvent: 'string' | null;
  252. firstTransactionEvent: boolean;
  253. subjectTemplate: string;
  254. digestsMaxDelay: number;
  255. digestsMinDelay: number;
  256. environments: string[];
  257. eventProcessing: {
  258. symbolicationDegraded: boolean;
  259. };
  260. // XXX: These are part of the DetailedProject serializer
  261. dynamicSampling: {
  262. next_id: number;
  263. rules: DynamicSamplingRules;
  264. } | null;
  265. plugins: Plugin[];
  266. processingIssues: number;
  267. relayPiiConfig: string;
  268. groupingConfig: string;
  269. latestDeploys?: Record<string, Pick<Deploy, 'dateFinished' | 'version'>> | null;
  270. builtinSymbolSources?: string[];
  271. symbolSources?: string;
  272. stats?: TimeseriesValue[];
  273. transactionStats?: TimeseriesValue[];
  274. latestRelease?: Release;
  275. options?: Record<string, boolean | string>;
  276. sessionStats?: {
  277. currentCrashFreeRate: number | null;
  278. previousCrashFreeRate: number | null;
  279. hasHealthData: boolean;
  280. };
  281. } & AvatarProject;
  282. export type MinimalProject = Pick<Project, 'id' | 'slug' | 'platform'>;
  283. // Response from project_keys endpoints.
  284. export type ProjectKey = {
  285. id: string;
  286. name: string;
  287. label: string;
  288. public: string;
  289. secret: string;
  290. projectId: string;
  291. isActive: boolean;
  292. rateLimit: {
  293. window: string;
  294. count: number;
  295. } | null;
  296. dsn: {
  297. secret: string;
  298. public: string;
  299. csp: string;
  300. security: string;
  301. minidump: string;
  302. unreal: string;
  303. cdn: string;
  304. };
  305. browserSdkVersion: string;
  306. browserSdk: {
  307. choices: [key: string, value: string][];
  308. };
  309. dateCreated: string;
  310. };
  311. export type Health = {
  312. totalUsers: number;
  313. totalUsers24h: number | null;
  314. totalProjectUsers24h: number | null;
  315. totalSessions: number;
  316. totalSessions24h: number | null;
  317. totalProjectSessions24h: number | null;
  318. crashFreeUsers: number | null;
  319. crashFreeSessions: number | null;
  320. stats: HealthGraphData;
  321. sessionsCrashed: number;
  322. sessionsErrored: number;
  323. adoption: number | null;
  324. sessionsAdoption: number | null;
  325. hasHealthData: boolean;
  326. durationP50: number | null;
  327. durationP90: number | null;
  328. };
  329. export type HealthGraphData = Record<string, TimeseriesValue[]>;
  330. export type Team = {
  331. id: string;
  332. name: string;
  333. slug: string;
  334. isMember: boolean;
  335. hasAccess: boolean;
  336. isPending: boolean;
  337. memberCount: number;
  338. avatar: Avatar;
  339. externalTeams: ExternalTeam[];
  340. };
  341. export type TeamWithProjects = Team & {projects: Project[]};
  342. export type TreeLabelPart =
  343. | string
  344. | {
  345. function?: string;
  346. package?: string;
  347. type?: string;
  348. classbase?: string;
  349. filebase?: string;
  350. datapath?: (string | number)[];
  351. // is_sentinel is no longer being used,
  352. // but we will still assess whether we will use this property in the near future.
  353. is_sentinel?: boolean;
  354. is_prefix?: boolean;
  355. };
  356. // This type is incomplete
  357. export type EventMetadata = {
  358. value?: string;
  359. message?: string;
  360. directive?: string;
  361. type?: string;
  362. title?: string;
  363. uri?: string;
  364. filename?: string;
  365. origin?: string;
  366. function?: string;
  367. stripped_crash?: boolean;
  368. current_tree_label?: TreeLabelPart[];
  369. finest_tree_label?: TreeLabelPart[];
  370. current_level?: number;
  371. };
  372. // endpoint: /api/0/issues/:issueId/attachments/?limit=50
  373. export type IssueAttachment = {
  374. id: string;
  375. dateCreated: string;
  376. headers: Object;
  377. mimetype: string;
  378. name: string;
  379. sha1: string;
  380. size: number;
  381. type: string;
  382. event_id: string;
  383. };
  384. // endpoint: /api/0/projects/:orgSlug/:projSlug/events/:eventId/attachments/
  385. export type EventAttachment = Omit<IssueAttachment, 'event_id'>;
  386. export type EntryData = Record<string, any | Array<any>>;
  387. type EnableIntegrationSuggestion = {
  388. type: 'enableIntegration';
  389. integrationName: string;
  390. enables: Array<SDKUpdatesSuggestion>;
  391. integrationUrl?: string | null;
  392. };
  393. export type UpdateSdkSuggestion = {
  394. type: 'updateSdk';
  395. sdkName: string;
  396. newSdkVersion: string;
  397. enables: Array<SDKUpdatesSuggestion>;
  398. sdkUrl?: string | null;
  399. };
  400. type ChangeSdkSuggestion = {
  401. type: 'changeSdk';
  402. newSdkName: string;
  403. enables: Array<SDKUpdatesSuggestion>;
  404. sdkUrl?: string | null;
  405. };
  406. export type SDKUpdatesSuggestion =
  407. | EnableIntegrationSuggestion
  408. | UpdateSdkSuggestion
  409. | ChangeSdkSuggestion;
  410. export type ProjectSdkUpdates = {
  411. projectId: string;
  412. sdkName: string;
  413. sdkVersion: string;
  414. suggestions: SDKUpdatesSuggestion[];
  415. };
  416. export type EventsStatsData = [number, {count: number}[]][];
  417. // API response format for a single series
  418. export type EventsStats = {
  419. data: EventsStatsData;
  420. totals?: {count: number};
  421. order?: number;
  422. start?: number;
  423. end?: number;
  424. };
  425. // API response format for multiple series
  426. export type MultiSeriesEventsStats = {
  427. [seriesName: string]: EventsStats;
  428. };
  429. /**
  430. * Avatars are a more primitive version of User.
  431. */
  432. export type AvatarUser = {
  433. id: string;
  434. name: string;
  435. username: string;
  436. email: string;
  437. ip_address: string;
  438. avatarUrl?: string;
  439. avatar?: Avatar;
  440. // Compatibility shim with EventUser serializer
  441. ipAddress?: string;
  442. options?: {
  443. avatarType: Avatar['avatarType'];
  444. };
  445. lastSeen?: string;
  446. };
  447. /**
  448. * This is an authenticator that a user is enrolled in
  449. */
  450. type UserEnrolledAuthenticator = {
  451. dateUsed: EnrolledAuthenticator['lastUsedAt'];
  452. dateCreated: EnrolledAuthenticator['createdAt'];
  453. type: Authenticator['id'];
  454. id: EnrolledAuthenticator['authId'];
  455. name: EnrolledAuthenticator['name'];
  456. };
  457. export type User = Omit<AvatarUser, 'options'> & {
  458. lastLogin: string;
  459. isSuperuser: boolean;
  460. isAuthenticated: boolean;
  461. emails: {
  462. is_verified: boolean;
  463. id: string;
  464. email: string;
  465. }[];
  466. isManaged: boolean;
  467. lastActive: string;
  468. isStaff: boolean;
  469. identities: any[];
  470. isActive: boolean;
  471. has2fa: boolean;
  472. canReset2fa: boolean;
  473. authenticators: UserEnrolledAuthenticator[];
  474. dateJoined: string;
  475. options: {
  476. theme: 'system' | 'light' | 'dark';
  477. timezone: string;
  478. stacktraceOrder: number;
  479. language: string;
  480. clock24Hours: boolean;
  481. avatarType: Avatar['avatarType'];
  482. };
  483. flags: {newsletter_consent_prompt: boolean};
  484. hasPasswordAuth: boolean;
  485. permissions: Set<string>;
  486. experiments: Partial<UserExperiments>;
  487. };
  488. // XXX(epurkhiser): we should understand how this is diff from User['emails]
  489. // above
  490. export type UserEmail = {
  491. email: string;
  492. isPrimary: boolean;
  493. isVerified: boolean;
  494. };
  495. export type CommitAuthor = {
  496. email?: string;
  497. name?: string;
  498. };
  499. export type Environment = {
  500. id: string;
  501. displayName: string;
  502. name: string;
  503. // XXX: Provided by the backend but unused due to `getUrlRoutingName()`
  504. // urlRoutingName: string;
  505. };
  506. export type RecentSearch = {
  507. id: string;
  508. organizationId: string;
  509. type: SavedSearchType;
  510. query: string;
  511. lastSeen: string;
  512. dateCreated: string;
  513. };
  514. // XXX: Deprecated Sentry 9 attributes are not included here.
  515. export type SavedSearch = {
  516. id: string;
  517. type: SavedSearchType;
  518. name: string;
  519. query: string;
  520. sort: string;
  521. isGlobal: boolean;
  522. isPinned: boolean;
  523. isOrgCustom: boolean;
  524. dateCreated: string;
  525. };
  526. export enum SavedSearchType {
  527. ISSUE = 0,
  528. EVENT = 1,
  529. }
  530. export type PluginNoProject = {
  531. id: string;
  532. name: string;
  533. slug: string;
  534. shortName: string;
  535. type: string;
  536. canDisable: boolean;
  537. isTestable: boolean;
  538. hasConfiguration: boolean;
  539. metadata: any; // TODO(ts)
  540. contexts: any[]; // TODO(ts)
  541. status: string;
  542. assets: Array<{url: string}>;
  543. doc: string;
  544. features: string[];
  545. featureDescriptions: IntegrationFeature[];
  546. isHidden: boolean;
  547. version?: string;
  548. author?: {name: string; url: string};
  549. description?: string;
  550. resourceLinks?: Array<{title: string; url: string}>;
  551. altIsSentryApp?: boolean;
  552. deprecationDate?: string;
  553. firstPartyAlternative?: string;
  554. };
  555. export type Plugin = PluginNoProject & {
  556. enabled: boolean;
  557. };
  558. export type PluginProjectItem = {
  559. projectId: string;
  560. projectSlug: string;
  561. projectName: string;
  562. projectPlatform: PlatformKey;
  563. enabled: boolean;
  564. configured: boolean;
  565. };
  566. export type PluginWithProjectList = PluginNoProject & {
  567. projectList: PluginProjectItem[];
  568. };
  569. export type AppOrProviderOrPlugin =
  570. | SentryApp
  571. | IntegrationProvider
  572. | PluginWithProjectList
  573. | DocumentIntegration;
  574. export type IntegrationType = 'document' | 'plugin' | 'first_party' | 'sentry_app';
  575. export type DocumentIntegration = {
  576. slug: string;
  577. name: string;
  578. author: string;
  579. docUrl: string;
  580. description: string;
  581. features: IntegrationFeature[];
  582. resourceLinks: Array<{title: string; url: string}>;
  583. };
  584. export type DateString = Date | string | null;
  585. export type RelativePeriod = keyof typeof DEFAULT_RELATIVE_PERIODS;
  586. export type IntervalPeriod = ReturnType<typeof getInterval>;
  587. export type GlobalSelection = {
  588. // Project Ids currently selected
  589. projects: number[];
  590. environments: string[];
  591. datetime: {
  592. start: DateString;
  593. end: DateString;
  594. period: RelativePeriod | string;
  595. utc: boolean | null;
  596. };
  597. };
  598. export type AuthenticatorDevice = {
  599. key_handle: string;
  600. authId: string;
  601. name: string;
  602. timestamp?: string;
  603. };
  604. export type Authenticator = {
  605. /**
  606. * String used to display on button for user as CTA to enroll
  607. */
  608. enrollButton: string;
  609. /**
  610. * Display name for the authenticator
  611. */
  612. name: string;
  613. /**
  614. * Allows multiple enrollments to authenticator
  615. */
  616. allowMultiEnrollment: boolean;
  617. /**
  618. * Allows authenticator's secret to be rotated without disabling
  619. */
  620. allowRotationInPlace: boolean;
  621. /**
  622. * String to display on button for user to remove authenticator
  623. */
  624. removeButton: string | null;
  625. canValidateOtp: boolean;
  626. /**
  627. * Is user enrolled to this authenticator
  628. */
  629. isEnrolled: boolean;
  630. /**
  631. * String to display on button for additional information about authenticator
  632. */
  633. configureButton: string;
  634. /**
  635. * Is this used as a backup interface?
  636. */
  637. isBackupInterface: boolean;
  638. /**
  639. * Description of the authenticator
  640. */
  641. description: string;
  642. rotationWarning: string | null;
  643. status: string;
  644. createdAt: string | null;
  645. lastUsedAt: string | null;
  646. codes: string[];
  647. devices: AuthenticatorDevice[];
  648. phone?: string;
  649. secret?: string;
  650. /**
  651. * The form configuration for the authenticator is present during enrollment
  652. */
  653. form?: Field[];
  654. } & Partial<EnrolledAuthenticator> &
  655. (
  656. | {
  657. id: 'sms';
  658. }
  659. | {
  660. id: 'totp';
  661. qrcode: string;
  662. }
  663. | {
  664. id: 'u2f';
  665. challenge: ChallengeData;
  666. }
  667. );
  668. export type ChallengeData = {
  669. authenticateRequests: u2f.SignRequest;
  670. registerRequests: u2f.RegisterRequest;
  671. };
  672. export type EnrolledAuthenticator = {
  673. lastUsedAt: string | null;
  674. createdAt: string;
  675. authId: string;
  676. name: string;
  677. };
  678. export interface Config {
  679. theme: 'light' | 'dark';
  680. languageCode: string;
  681. csrfCookieName: string;
  682. features: Set<string>;
  683. singleOrganization: boolean;
  684. urlPrefix: string;
  685. needsUpgrade: boolean;
  686. supportEmail: string;
  687. user: User;
  688. invitesEnabled: boolean;
  689. privacyUrl: string | null;
  690. isOnPremise: boolean;
  691. lastOrganization: string | null;
  692. gravatarBaseUrl: string;
  693. /**
  694. * This comes from django (django.contrib.messages)
  695. */
  696. messages: {message: string; level: string}[];
  697. dsn: string;
  698. userIdentity: {ip_address: string; email: string; id: string; isStaff: boolean};
  699. termsUrl: string | null;
  700. isAuthenticated: boolean;
  701. version: {
  702. current: string;
  703. build: string;
  704. upgradeAvailable: boolean;
  705. latest: string;
  706. };
  707. statuspage?: {
  708. id: string;
  709. api_host: string;
  710. };
  711. sentryConfig: {
  712. dsn: string;
  713. release: string;
  714. whitelistUrls: string[];
  715. };
  716. distPrefix: string;
  717. apmSampling: number;
  718. dsn_requests: string;
  719. demoMode: boolean;
  720. }
  721. // https://github.com/getsentry/relay/blob/master/relay-common/src/constants.rs
  722. // Note: the value of the enum on the frontend is plural,
  723. // but the value of the enum on the backend is singular
  724. export enum DataCategory {
  725. DEFAULT = 'default',
  726. ERRORS = 'errors',
  727. TRANSACTIONS = 'transactions',
  728. ATTACHMENTS = 'attachments',
  729. }
  730. export type EventType = 'error' | 'transaction' | 'attachment';
  731. export const DataCategoryName = {
  732. [DataCategory.ERRORS]: 'Errors',
  733. [DataCategory.TRANSACTIONS]: 'Transactions',
  734. [DataCategory.ATTACHMENTS]: 'Attachments',
  735. };
  736. export enum EventOrGroupType {
  737. ERROR = 'error',
  738. CSP = 'csp',
  739. HPKP = 'hpkp',
  740. EXPECTCT = 'expectct',
  741. EXPECTSTAPLE = 'expectstaple',
  742. DEFAULT = 'default',
  743. TRANSACTION = 'transaction',
  744. }
  745. export type InboxReasonDetails = {
  746. until?: string | null;
  747. count?: number | null;
  748. window?: number | null;
  749. user_count?: number | null;
  750. user_window?: number | null;
  751. };
  752. export type InboxDetails = {
  753. reason_details: InboxReasonDetails;
  754. date_added?: string;
  755. reason?: number;
  756. };
  757. export type SuggestedOwnerReason = 'suspectCommit' | 'ownershipRule';
  758. // Received from the backend to denote suggested owners of an issue
  759. export type SuggestedOwner = {
  760. type: SuggestedOwnerReason;
  761. owner: string;
  762. date_added: string;
  763. };
  764. export enum GroupActivityType {
  765. NOTE = 'note',
  766. SET_RESOLVED = 'set_resolved',
  767. SET_RESOLVED_BY_AGE = 'set_resolved_by_age',
  768. SET_RESOLVED_IN_RELEASE = 'set_resolved_in_release',
  769. SET_RESOLVED_IN_COMMIT = 'set_resolved_in_commit',
  770. SET_RESOLVED_IN_PULL_REQUEST = 'set_resolved_in_pull_request',
  771. SET_UNRESOLVED = 'set_unresolved',
  772. SET_IGNORED = 'set_ignored',
  773. SET_PUBLIC = 'set_public',
  774. SET_PRIVATE = 'set_private',
  775. SET_REGRESSION = 'set_regression',
  776. CREATE_ISSUE = 'create_issue',
  777. UNMERGE_SOURCE = 'unmerge_source',
  778. UNMERGE_DESTINATION = 'unmerge_destination',
  779. FIRST_SEEN = 'first_seen',
  780. ASSIGNED = 'assigned',
  781. UNASSIGNED = 'unassigned',
  782. MERGE = 'merge',
  783. REPROCESS = 'reprocess',
  784. MARK_REVIEWED = 'mark_reviewed',
  785. }
  786. type GroupActivityBase = {
  787. dateCreated: string;
  788. id: string;
  789. project: Project;
  790. user?: null | User;
  791. assignee?: string;
  792. issue?: Group;
  793. };
  794. type GroupActivityNote = GroupActivityBase & {
  795. type: GroupActivityType.NOTE;
  796. data: {
  797. text: string;
  798. };
  799. };
  800. type GroupActivitySetResolved = GroupActivityBase & {
  801. type: GroupActivityType.SET_RESOLVED;
  802. data: Record<string, any>;
  803. };
  804. type GroupActivitySetUnresolved = GroupActivityBase & {
  805. type: GroupActivityType.SET_UNRESOLVED;
  806. data: Record<string, any>;
  807. };
  808. type GroupActivitySetPublic = GroupActivityBase & {
  809. type: GroupActivityType.SET_PUBLIC;
  810. data: Record<string, any>;
  811. };
  812. type GroupActivitySetPrivate = GroupActivityBase & {
  813. type: GroupActivityType.SET_PRIVATE;
  814. data: Record<string, any>;
  815. };
  816. type GroupActivitySetByAge = GroupActivityBase & {
  817. type: GroupActivityType.SET_RESOLVED_BY_AGE;
  818. data: Record<string, any>;
  819. };
  820. type GroupActivityUnassigned = GroupActivityBase & {
  821. type: GroupActivityType.UNASSIGNED;
  822. data: Record<string, any>;
  823. };
  824. type GroupActivityFirstSeen = GroupActivityBase & {
  825. type: GroupActivityType.FIRST_SEEN;
  826. data: Record<string, any>;
  827. };
  828. type GroupActivityMarkReviewed = GroupActivityBase & {
  829. type: GroupActivityType.MARK_REVIEWED;
  830. data: Record<string, any>;
  831. };
  832. type GroupActivityRegression = GroupActivityBase & {
  833. type: GroupActivityType.SET_REGRESSION;
  834. data: {
  835. version?: string;
  836. };
  837. };
  838. export type GroupActivitySetByResolvedInRelease = GroupActivityBase & {
  839. type: GroupActivityType.SET_RESOLVED_IN_RELEASE;
  840. data: {
  841. version?: string;
  842. current_release_version?: string;
  843. };
  844. };
  845. type GroupActivitySetByResolvedInCommit = GroupActivityBase & {
  846. type: GroupActivityType.SET_RESOLVED_IN_COMMIT;
  847. data: {
  848. commit: Commit;
  849. };
  850. };
  851. type GroupActivitySetByResolvedInPullRequest = GroupActivityBase & {
  852. type: GroupActivityType.SET_RESOLVED_IN_PULL_REQUEST;
  853. data: {
  854. pullRequest: PullRequest;
  855. };
  856. };
  857. export type GroupActivitySetIgnored = GroupActivityBase & {
  858. type: GroupActivityType.SET_IGNORED;
  859. data: {
  860. ignoreDuration?: number;
  861. ignoreUntil?: string;
  862. ignoreUserCount?: number;
  863. ignoreUserWindow?: number;
  864. ignoreWindow?: number;
  865. ignoreCount?: number;
  866. };
  867. };
  868. export type GroupActivityReprocess = GroupActivityBase & {
  869. type: GroupActivityType.REPROCESS;
  870. data: {
  871. eventCount: number;
  872. newGroupId: number;
  873. oldGroupId: number;
  874. };
  875. };
  876. type GroupActivityUnmergeDestination = GroupActivityBase & {
  877. type: GroupActivityType.UNMERGE_DESTINATION;
  878. data: {
  879. fingerprints: Array<string>;
  880. source?: {
  881. id: string;
  882. shortId: string;
  883. };
  884. };
  885. };
  886. type GroupActivityUnmergeSource = GroupActivityBase & {
  887. type: GroupActivityType.UNMERGE_SOURCE;
  888. data: {
  889. fingerprints: Array<string>;
  890. destination?: {
  891. id: string;
  892. shortId: string;
  893. };
  894. };
  895. };
  896. type GroupActivityMerge = GroupActivityBase & {
  897. type: GroupActivityType.MERGE;
  898. data: {
  899. issues: Array<any>;
  900. };
  901. };
  902. export type GroupActivityAssigned = GroupActivityBase & {
  903. type: GroupActivityType.ASSIGNED;
  904. data: {
  905. assignee: string;
  906. assigneeType: string;
  907. user: Team | User;
  908. };
  909. };
  910. export type GroupActivityCreateIssue = GroupActivityBase & {
  911. type: GroupActivityType.CREATE_ISSUE;
  912. data: {
  913. provider: string;
  914. location: string;
  915. title: string;
  916. };
  917. };
  918. export type GroupActivity =
  919. | GroupActivityNote
  920. | GroupActivitySetResolved
  921. | GroupActivitySetUnresolved
  922. | GroupActivitySetIgnored
  923. | GroupActivitySetByAge
  924. | GroupActivitySetByResolvedInRelease
  925. | GroupActivitySetByResolvedInCommit
  926. | GroupActivitySetByResolvedInPullRequest
  927. | GroupActivityFirstSeen
  928. | GroupActivityMerge
  929. | GroupActivityReprocess
  930. | GroupActivityUnassigned
  931. | GroupActivityMarkReviewed
  932. | GroupActivityUnmergeDestination
  933. | GroupActivitySetPublic
  934. | GroupActivitySetPrivate
  935. | GroupActivityRegression
  936. | GroupActivityUnmergeSource
  937. | GroupActivityAssigned
  938. | GroupActivityCreateIssue;
  939. export type Activity = GroupActivity;
  940. type GroupFiltered = {
  941. count: string;
  942. stats: Record<string, TimeseriesValue[]>;
  943. lastSeen: string;
  944. firstSeen: string;
  945. userCount: number;
  946. };
  947. export type GroupStats = GroupFiltered & {
  948. lifetime?: GroupFiltered;
  949. filtered: GroupFiltered | null;
  950. sessionCount?: string | null;
  951. id: string;
  952. };
  953. export type BaseGroupStatusReprocessing = {
  954. status: 'reprocessing';
  955. statusDetails: {
  956. pendingEvents: number;
  957. info: {
  958. dateCreated: string;
  959. totalEvents: number;
  960. } | null;
  961. };
  962. };
  963. type BaseGroupStatusResolution = {
  964. status: ResolutionStatus;
  965. statusDetails: ResolutionStatusDetails;
  966. };
  967. export type GroupRelease = {
  968. firstRelease: Release;
  969. lastRelease: Release;
  970. };
  971. // TODO(ts): incomplete
  972. export type BaseGroup = {
  973. id: string;
  974. latestEvent: Event;
  975. activity: GroupActivity[];
  976. annotations: string[];
  977. assignedTo: Actor;
  978. culprit: string;
  979. firstSeen: string;
  980. hasSeen: boolean;
  981. isBookmarked: boolean;
  982. isUnhandled: boolean;
  983. isPublic: boolean;
  984. isSubscribed: boolean;
  985. lastSeen: string;
  986. level: Level;
  987. logger: string;
  988. metadata: EventMetadata;
  989. numComments: number;
  990. participants: User[];
  991. permalink: string;
  992. platform: PlatformKey;
  993. pluginActions: any[]; // TODO(ts)
  994. pluginContexts: any[]; // TODO(ts)
  995. pluginIssues: any[]; // TODO(ts)
  996. project: Project;
  997. seenBy: User[];
  998. shareId: string;
  999. shortId: string;
  1000. tags: Pick<Tag, 'key' | 'name' | 'totalValues'>[];
  1001. title: string;
  1002. type: EventOrGroupType;
  1003. userReportCount: number;
  1004. subscriptionDetails: {disabled?: boolean; reason?: string} | null;
  1005. status: string;
  1006. inbox?: InboxDetails | null | false;
  1007. owners?: SuggestedOwner[] | null;
  1008. } & GroupRelease;
  1009. export type GroupReprocessing = BaseGroup & GroupStats & BaseGroupStatusReprocessing;
  1010. export type GroupResolution = BaseGroup & GroupStats & BaseGroupStatusResolution;
  1011. export type Group = GroupResolution | GroupReprocessing;
  1012. export type GroupCollapseRelease = Omit<Group, keyof GroupRelease> &
  1013. Partial<GroupRelease>;
  1014. export type GroupTombstone = {
  1015. id: string;
  1016. title: string;
  1017. culprit: string;
  1018. level: Level;
  1019. actor: AvatarUser;
  1020. metadata: EventMetadata;
  1021. };
  1022. export type ProcessingIssueItem = {
  1023. id: string;
  1024. type: string;
  1025. checksum: string;
  1026. numEvents: number;
  1027. data: {
  1028. // TODO(ts) This type is likely incomplete, but this is what
  1029. // project processing issues settings uses.
  1030. _scope: string;
  1031. image_arch: string;
  1032. image_uuid: string;
  1033. image_path: string;
  1034. };
  1035. lastSeen: string;
  1036. };
  1037. export type ProcessingIssue = {
  1038. project: string;
  1039. numIssues: number;
  1040. signedLink: string;
  1041. lastSeen: string;
  1042. hasMoreResolveableIssues: boolean;
  1043. hasIssues: boolean;
  1044. issuesProcessing: number;
  1045. resolveableIssues: number;
  1046. issues?: ProcessingIssueItem[];
  1047. };
  1048. /**
  1049. * Returned from /organizations/org/users/
  1050. */
  1051. export type Member = {
  1052. dateCreated: string;
  1053. email: string;
  1054. expired: boolean;
  1055. flags: {
  1056. 'sso:linked': boolean;
  1057. 'sso:invalid': boolean;
  1058. 'member-limit:restricted': boolean;
  1059. };
  1060. id: string;
  1061. inviteStatus: 'approved' | 'requested_to_be_invited' | 'requested_to_join';
  1062. invite_link: string | null;
  1063. inviterName: string | null;
  1064. isOnlyOwner: boolean;
  1065. name: string;
  1066. pending: boolean | undefined;
  1067. projects: string[];
  1068. role: string;
  1069. roleName: string;
  1070. roles: MemberRole[]; // TODO(ts): This is not present from API call
  1071. teams: string[];
  1072. user: User;
  1073. };
  1074. export type AccessRequest = {
  1075. id: string;
  1076. team: Team;
  1077. member: Member;
  1078. requester?: Partial<{
  1079. name: string;
  1080. username: string;
  1081. email: string;
  1082. }>;
  1083. };
  1084. export type Repository = {
  1085. dateCreated: string;
  1086. externalSlug: string;
  1087. id: string;
  1088. integrationId: string;
  1089. name: string;
  1090. provider: {id: string; name: string};
  1091. status: RepositoryStatus;
  1092. url: string;
  1093. };
  1094. export enum RepositoryStatus {
  1095. ACTIVE = 'active',
  1096. DISABLED = 'disabled',
  1097. HIDDEN = 'hidden',
  1098. PENDING_DELETION = 'pending_deletion',
  1099. DELETION_IN_PROGRESS = 'deletion_in_progress',
  1100. }
  1101. type BaseRepositoryProjectPathConfig = {
  1102. id: string;
  1103. projectId: string;
  1104. projectSlug: string;
  1105. repoId: string;
  1106. repoName: string;
  1107. stackRoot: string;
  1108. sourceRoot: string;
  1109. defaultBranch?: string;
  1110. };
  1111. export type RepositoryProjectPathConfig = BaseRepositoryProjectPathConfig & {
  1112. integrationId: string | null;
  1113. provider: BaseIntegrationProvider | null;
  1114. };
  1115. export type RepositoryProjectPathConfigWithIntegration =
  1116. BaseRepositoryProjectPathConfig & {
  1117. integrationId: string;
  1118. provider: BaseIntegrationProvider;
  1119. };
  1120. export type PullRequest = {
  1121. id: string;
  1122. title: string;
  1123. externalUrl: string;
  1124. repository: Repository;
  1125. };
  1126. type IntegrationDialog = {
  1127. actionText: string;
  1128. body: string;
  1129. };
  1130. type IntegrationAspects = {
  1131. alerts?: Array<React.ComponentProps<typeof Alert> & {text: string}>;
  1132. disable_dialog?: IntegrationDialog;
  1133. removal_dialog?: IntegrationDialog;
  1134. externalInstall?: {
  1135. url: string;
  1136. buttonText: string;
  1137. noticeText: string;
  1138. };
  1139. configure_integration?: {
  1140. title: string;
  1141. };
  1142. };
  1143. type BaseIntegrationProvider = {
  1144. key: string;
  1145. slug: string;
  1146. name: string;
  1147. canAdd: boolean;
  1148. canDisable: boolean;
  1149. features: string[];
  1150. };
  1151. export type IntegrationProvider = BaseIntegrationProvider & {
  1152. setupDialog: {url: string; width: number; height: number};
  1153. metadata: {
  1154. description: string;
  1155. features: IntegrationFeature[];
  1156. author: string;
  1157. noun: string;
  1158. issue_url: string;
  1159. source_url: string;
  1160. aspects: IntegrationAspects;
  1161. };
  1162. };
  1163. export type IntegrationFeature = {
  1164. description: string;
  1165. featureGate: string;
  1166. };
  1167. export type WebhookEvent = 'issue' | 'error';
  1168. export type Scope = typeof API_ACCESS_SCOPES[number];
  1169. export type SentryAppSchemaIssueLink = {
  1170. type: 'issue-link';
  1171. create: {
  1172. uri: string;
  1173. required_fields: any[];
  1174. optional_fields?: any[];
  1175. };
  1176. link: {
  1177. uri: string;
  1178. required_fields: any[];
  1179. optional_fields?: any[];
  1180. };
  1181. };
  1182. export type SentryAppSchemaStacktraceLink = {
  1183. type: 'stacktrace-link';
  1184. uri: string;
  1185. url: string;
  1186. params?: Array<string>;
  1187. };
  1188. export type SentryAppSchemaElement =
  1189. | SentryAppSchemaIssueLink
  1190. | SentryAppSchemaStacktraceLink;
  1191. export type SentryApp = {
  1192. status: SentryAppStatus;
  1193. scopes: Scope[];
  1194. isAlertable: boolean;
  1195. verifyInstall: boolean;
  1196. slug: string;
  1197. name: string;
  1198. uuid: string;
  1199. author: string;
  1200. events: WebhookEvent[];
  1201. schema: {
  1202. elements?: SentryAppSchemaElement[];
  1203. };
  1204. // possible null params
  1205. webhookUrl: string | null;
  1206. redirectUrl: string | null;
  1207. overview: string | null;
  1208. // optional params below
  1209. datePublished?: string;
  1210. clientId?: string;
  1211. clientSecret?: string;
  1212. owner?: {
  1213. id: number;
  1214. slug: string;
  1215. };
  1216. featureData: IntegrationFeature[];
  1217. };
  1218. export type Integration = {
  1219. id: string;
  1220. name: string;
  1221. icon: string;
  1222. domainName: string;
  1223. accountType: string;
  1224. scopes?: string[];
  1225. status: ObjectStatus;
  1226. provider: BaseIntegrationProvider & {aspects: IntegrationAspects};
  1227. dynamicDisplayInformation?: {
  1228. configure_integration?: {
  1229. instructions: string[];
  1230. };
  1231. integration_detail?: {
  1232. uninstallationUrl?: string;
  1233. };
  1234. };
  1235. };
  1236. // we include the configOrganization when we need it
  1237. export type IntegrationWithConfig = Integration & {
  1238. configOrganization: Field[];
  1239. configData: object | null;
  1240. };
  1241. export type IntegrationExternalIssue = {
  1242. id: string;
  1243. key: string;
  1244. url: string;
  1245. title: string;
  1246. description: string;
  1247. displayName: string;
  1248. };
  1249. export type GroupIntegration = Integration & {
  1250. externalIssues: IntegrationExternalIssue[];
  1251. };
  1252. export type PlatformExternalIssue = {
  1253. id: string;
  1254. issueId: string;
  1255. serviceType: string;
  1256. displayName: string;
  1257. webUrl: string;
  1258. };
  1259. export type SentryAppInstallation = {
  1260. app: {
  1261. uuid: string;
  1262. slug: string;
  1263. };
  1264. organization: {
  1265. slug: string;
  1266. };
  1267. uuid: string;
  1268. status: 'installed' | 'pending';
  1269. code?: string;
  1270. };
  1271. export type SentryAppWebhookRequest = {
  1272. webhookUrl: string;
  1273. sentryAppSlug: string;
  1274. eventType: string;
  1275. date: string;
  1276. organization?: {
  1277. slug: string;
  1278. name: string;
  1279. };
  1280. responseCode: number;
  1281. errorUrl?: string;
  1282. };
  1283. export type ServiceHook = {
  1284. id: string;
  1285. events: string[];
  1286. dateCreated: string;
  1287. secret: string;
  1288. status: string;
  1289. url: string;
  1290. };
  1291. export type PermissionValue = 'no-access' | 'read' | 'write' | 'admin';
  1292. export type Permissions = {
  1293. Event: PermissionValue;
  1294. Member: PermissionValue;
  1295. Organization: PermissionValue;
  1296. Project: PermissionValue;
  1297. Release: PermissionValue;
  1298. Team: PermissionValue;
  1299. };
  1300. // See src/sentry/api/serializers/models/apitoken.py for the differences based on application
  1301. type BaseApiToken = {
  1302. id: string;
  1303. scopes: Scope[];
  1304. expiresAt: string;
  1305. dateCreated: string;
  1306. state: string;
  1307. };
  1308. // We include the token for API tokens used for internal apps
  1309. export type InternalAppApiToken = BaseApiToken & {
  1310. application: null;
  1311. token: string;
  1312. refreshToken: string;
  1313. };
  1314. export type ApiApplication = {
  1315. allowedOrigins: string[];
  1316. clientID: string;
  1317. clientSecret: string | null;
  1318. homepageUrl: string | null;
  1319. id: string;
  1320. name: string;
  1321. privacyUrl: string | null;
  1322. redirectUris: string[];
  1323. termsUrl: string | null;
  1324. };
  1325. export type UserReport = {
  1326. id: string;
  1327. eventID: string;
  1328. issue: Group;
  1329. name: string;
  1330. event: {eventID: string; id: string};
  1331. user: User;
  1332. dateCreated: string;
  1333. comments: string;
  1334. email: string;
  1335. };
  1336. export type Release = BaseRelease &
  1337. ReleaseData & {
  1338. projects: ReleaseProject[];
  1339. };
  1340. export type ReleaseWithHealth = BaseRelease &
  1341. ReleaseData & {
  1342. projects: Required<ReleaseProject>[];
  1343. };
  1344. type ReleaseData = {
  1345. commitCount: number;
  1346. data: {};
  1347. lastDeploy?: Deploy;
  1348. deployCount: number;
  1349. lastEvent: string;
  1350. firstEvent: string;
  1351. lastCommit?: Commit;
  1352. authors: User[];
  1353. owner?: any; // TODO(ts)
  1354. newGroups: number;
  1355. versionInfo: VersionInfo;
  1356. fileCount: number | null;
  1357. currentProjectMeta: {
  1358. nextReleaseVersion: string | null;
  1359. prevReleaseVersion: string | null;
  1360. sessionsLowerBound: string | null;
  1361. sessionsUpperBound: string | null;
  1362. firstReleaseVersion: string | null;
  1363. lastReleaseVersion: string | null;
  1364. };
  1365. adoptionStages?: Record<
  1366. 'string',
  1367. {
  1368. stage: string | null;
  1369. adopted: string | null;
  1370. unadopted: string | null;
  1371. }
  1372. >;
  1373. };
  1374. type BaseRelease = {
  1375. dateReleased: string;
  1376. url: string;
  1377. dateCreated: string;
  1378. version: string;
  1379. shortVersion: string;
  1380. ref: string;
  1381. status: ReleaseStatus;
  1382. };
  1383. export type CurrentRelease = {
  1384. environment: string;
  1385. firstSeen: string;
  1386. lastSeen: string;
  1387. release: Release;
  1388. stats: {
  1389. // 24h/30d is hardcoded in GroupReleaseWithStatsSerializer
  1390. '24h': TimeseriesValue[];
  1391. '30d': TimeseriesValue[];
  1392. };
  1393. };
  1394. export enum ReleaseStatus {
  1395. Active = 'open',
  1396. Archived = 'archived',
  1397. }
  1398. export type ReleaseProject = {
  1399. slug: string;
  1400. name: string;
  1401. id: number;
  1402. platform: PlatformKey;
  1403. platforms: PlatformKey[];
  1404. newGroups: number;
  1405. hasHealthData: boolean;
  1406. healthData?: Health;
  1407. };
  1408. export type ReleaseMeta = {
  1409. commitCount: number;
  1410. commitFilesChanged: number;
  1411. deployCount: number;
  1412. releaseFileCount: number;
  1413. version: string;
  1414. projects: ReleaseProject[];
  1415. versionInfo: VersionInfo;
  1416. released: string;
  1417. };
  1418. export type VersionInfo = {
  1419. buildHash: string | null;
  1420. description: string;
  1421. package: string | null;
  1422. version: {raw: string};
  1423. };
  1424. export type Deploy = {
  1425. id: string;
  1426. name: string;
  1427. url: string;
  1428. environment: string;
  1429. dateStarted: string;
  1430. dateFinished: string;
  1431. version: string;
  1432. };
  1433. export type Commit = {
  1434. id: string;
  1435. message: string | null;
  1436. dateCreated: string;
  1437. releases: BaseRelease[];
  1438. repository?: Repository;
  1439. author?: User;
  1440. };
  1441. export type Committer = {
  1442. author: User;
  1443. commits: Commit[];
  1444. };
  1445. export type CommitFile = {
  1446. id: string;
  1447. author: CommitAuthor;
  1448. commitMessage: string;
  1449. filename: string;
  1450. orgId: number;
  1451. repoName: string;
  1452. type: string;
  1453. };
  1454. export type MemberRole = {
  1455. id: string;
  1456. name: string;
  1457. desc: string;
  1458. allowed?: boolean;
  1459. };
  1460. export type SentryAppComponent = {
  1461. uuid: string;
  1462. type: 'issue-link' | 'alert-rule-action' | 'issue-media' | 'stacktrace-link';
  1463. schema: SentryAppSchemaStacktraceLink;
  1464. sentryApp: {
  1465. uuid: string;
  1466. slug:
  1467. | 'calixa'
  1468. | 'clickup'
  1469. | 'komodor'
  1470. | 'linear'
  1471. | 'rookout'
  1472. | 'shortcut'
  1473. | 'spikesh'
  1474. | 'teamwork'
  1475. | 'zepel';
  1476. name: string;
  1477. };
  1478. };
  1479. export type SavedQueryVersions = 1 | 2;
  1480. export type NewQuery = {
  1481. id: string | undefined;
  1482. version: SavedQueryVersions;
  1483. name: string;
  1484. createdBy?: User;
  1485. // Query and Table
  1486. query?: string;
  1487. fields: Readonly<string[]>;
  1488. widths?: Readonly<string[]>;
  1489. orderby?: string;
  1490. expired?: boolean;
  1491. // GlobalSelectionHeader
  1492. projects: Readonly<number[]>;
  1493. environment?: Readonly<string[]>;
  1494. range?: string;
  1495. start?: string;
  1496. end?: string;
  1497. // Graph
  1498. yAxis?: string;
  1499. display?: string;
  1500. teams?: Readonly<('myteams' | number)[]>;
  1501. };
  1502. export type SavedQuery = NewQuery & {
  1503. id: string;
  1504. dateCreated: string;
  1505. dateUpdated: string;
  1506. };
  1507. export type SavedQueryState = {
  1508. savedQueries: SavedQuery[];
  1509. hasError: boolean;
  1510. isLoading: boolean;
  1511. };
  1512. /**
  1513. * The option format used by react-select based components
  1514. */
  1515. export type SelectValue<T> = {
  1516. label: string | number | React.ReactElement;
  1517. value: T;
  1518. disabled?: boolean;
  1519. tooltip?: string;
  1520. };
  1521. /**
  1522. * The 'other' option format used by checkboxes, radios and more.
  1523. */
  1524. export type Choices = [
  1525. value: string | number,
  1526. label: string | number | React.ReactElement
  1527. ][];
  1528. /**
  1529. * The issue config form fields we get are basically the form fields we use in
  1530. * the UI but with some extra information. Some fields marked optional in the
  1531. * form field are guaranteed to exist so we can mark them as required here
  1532. */
  1533. export type IssueConfigField = Field & {
  1534. name: string;
  1535. default?: string | number;
  1536. choices?: Choices;
  1537. url?: string;
  1538. multiple?: boolean;
  1539. };
  1540. export type IntegrationIssueConfig = {
  1541. status: ObjectStatus;
  1542. name: string;
  1543. domainName: string;
  1544. linkIssueConfig?: IssueConfigField[];
  1545. createIssueConfig?: IssueConfigField[];
  1546. provider: IntegrationProvider;
  1547. icon: string[];
  1548. };
  1549. export enum OnboardingTaskKey {
  1550. FIRST_PROJECT = 'create_project',
  1551. FIRST_EVENT = 'send_first_event',
  1552. INVITE_MEMBER = 'invite_member',
  1553. SECOND_PLATFORM = 'setup_second_platform',
  1554. USER_CONTEXT = 'setup_user_context',
  1555. RELEASE_TRACKING = 'setup_release_tracking',
  1556. SOURCEMAPS = 'setup_sourcemaps',
  1557. USER_REPORTS = 'setup_user_reports',
  1558. ISSUE_TRACKER = 'setup_issue_tracker',
  1559. ALERT_RULE = 'setup_alert_rules',
  1560. FIRST_TRANSACTION = 'setup_transactions',
  1561. }
  1562. export type OnboardingSupplementComponentProps = {
  1563. task: OnboardingTask;
  1564. onCompleteTask: () => void;
  1565. };
  1566. export type OnboardingTaskDescriptor = {
  1567. task: OnboardingTaskKey;
  1568. title: string;
  1569. description: string;
  1570. /**
  1571. * Can this task be skipped?
  1572. */
  1573. skippable: boolean;
  1574. /**
  1575. * A list of require task keys that must have been completed before these
  1576. * tasks may be completed.
  1577. */
  1578. requisites: OnboardingTaskKey[];
  1579. /**
  1580. * Should the onboarding task currently be displayed
  1581. */
  1582. display: boolean;
  1583. /**
  1584. * An extra component that may be rendered within the onboarding task item.
  1585. */
  1586. SupplementComponent?: React.ComponentType<OnboardingSupplementComponentProps>;
  1587. } & (
  1588. | {
  1589. actionType: 'app' | 'external';
  1590. location: string;
  1591. }
  1592. | {
  1593. actionType: 'action';
  1594. action: () => void;
  1595. }
  1596. );
  1597. export type OnboardingTaskStatus = {
  1598. task: OnboardingTaskKey;
  1599. status: 'skipped' | 'pending' | 'complete';
  1600. user?: AvatarUser | null;
  1601. dateCompleted?: string;
  1602. completionSeen?: string;
  1603. data?: object;
  1604. };
  1605. export type OnboardingTask = OnboardingTaskStatus &
  1606. OnboardingTaskDescriptor & {
  1607. /**
  1608. * Onboarding tasks that are currently incomplete and must be completed
  1609. * before this task should be completed.
  1610. */
  1611. requisiteTasks: OnboardingTask[];
  1612. };
  1613. export type Tag = {
  1614. name: string;
  1615. key: string;
  1616. values?: string[];
  1617. totalValues?: number;
  1618. predefined?: boolean;
  1619. isInput?: boolean;
  1620. /**
  1621. * How many values should be suggested in autocomplete.
  1622. * Overrides SmartSearchBar's `maxSearchItems` prop.
  1623. */
  1624. maxSuggestedValues?: number;
  1625. };
  1626. export type TagCollection = Record<string, Tag>;
  1627. export type TagValue = {
  1628. count: number;
  1629. name: string;
  1630. value: string;
  1631. lastSeen: string;
  1632. key: string;
  1633. firstSeen: string;
  1634. query?: string;
  1635. email?: string;
  1636. username?: string;
  1637. identifier?: string;
  1638. ipAddress?: string;
  1639. } & AvatarUser;
  1640. type Topvalue = {
  1641. count: number;
  1642. firstSeen: string;
  1643. key: string;
  1644. lastSeen: string;
  1645. name: string;
  1646. value: string;
  1647. // Might not actually exist.
  1648. query?: string;
  1649. };
  1650. export type TagWithTopValues = {
  1651. topValues: Array<Topvalue>;
  1652. key: string;
  1653. name: string;
  1654. totalValues: number;
  1655. uniqueValues: number;
  1656. canDelete?: boolean;
  1657. };
  1658. export type Level = 'error' | 'fatal' | 'info' | 'warning' | 'sample';
  1659. export type Meta = {
  1660. chunks: Array<ChunkType>;
  1661. len: number;
  1662. rem: Array<MetaRemark>;
  1663. err: Array<MetaError>;
  1664. };
  1665. export type MetaError = string | [string, any];
  1666. export type MetaRemark = Array<string | number>;
  1667. export type ChunkType = {
  1668. text: string;
  1669. type: string;
  1670. rule_id: string | number;
  1671. remark?: string | number;
  1672. };
  1673. export enum ResolutionStatus {
  1674. RESOLVED = 'resolved',
  1675. UNRESOLVED = 'unresolved',
  1676. IGNORED = 'ignored',
  1677. }
  1678. export type ResolutionStatusDetails = {
  1679. actor?: AvatarUser;
  1680. autoResolved?: boolean;
  1681. ignoreCount?: number;
  1682. // Sent in requests. ignoreUntil is used in responses.
  1683. ignoreDuration?: number;
  1684. ignoreUntil?: string;
  1685. ignoreUserCount?: number;
  1686. ignoreUserWindow?: number;
  1687. ignoreWindow?: number;
  1688. inCommit?: Commit;
  1689. inRelease?: string;
  1690. inNextRelease?: boolean;
  1691. };
  1692. export type UpdateResolutionStatus = {
  1693. status: ResolutionStatus;
  1694. statusDetails?: ResolutionStatusDetails;
  1695. };
  1696. export type SubscriptionDetails = {disabled?: boolean; reason?: string};
  1697. export type Broadcast = {
  1698. id: string;
  1699. message: string;
  1700. title: string;
  1701. link: string;
  1702. cta: string;
  1703. isActive: boolean;
  1704. dateCreated: string;
  1705. dateExpires: string;
  1706. hasSeen: boolean;
  1707. };
  1708. export type SentryServiceIncident = {
  1709. id: string;
  1710. name: string;
  1711. updates?: string[];
  1712. url: string;
  1713. status: string;
  1714. };
  1715. export type SentryServiceStatus = {
  1716. indicator: 'major' | 'minor' | 'none';
  1717. incidents: SentryServiceIncident[];
  1718. url: string;
  1719. };
  1720. export type CrashFreeTimeBreakdown = {
  1721. date: string;
  1722. totalSessions: number;
  1723. crashFreeSessions: number | null;
  1724. crashFreeUsers: number | null;
  1725. totalUsers: number;
  1726. }[];
  1727. export type PlatformIntegration = {
  1728. id: string;
  1729. type: string;
  1730. language: string;
  1731. link: string | null;
  1732. name: string;
  1733. };
  1734. export type EventGroupComponent = {
  1735. contributes: boolean;
  1736. hint: string | null;
  1737. id: string;
  1738. name: string | null;
  1739. values: EventGroupComponent[] | string[];
  1740. };
  1741. export type EventGroupingConfig = {
  1742. base: string | null;
  1743. changelog: string;
  1744. delegates: string[];
  1745. hidden: boolean;
  1746. id: string;
  1747. latest: boolean;
  1748. risk: number;
  1749. strategies: string[];
  1750. };
  1751. type EventGroupVariantKey = 'custom-fingerprint' | 'app' | 'default' | 'system';
  1752. export enum EventGroupVariantType {
  1753. CUSTOM_FINGERPRINT = 'custom-fingerprint',
  1754. COMPONENT = 'component',
  1755. SALTED_COMPONENT = 'salted-component',
  1756. }
  1757. export type EventGroupVariant = {
  1758. description: string | null;
  1759. hash: string | null;
  1760. hashMismatch: boolean;
  1761. key: EventGroupVariantKey;
  1762. type: EventGroupVariantType;
  1763. values?: Array<string>;
  1764. client_values?: Array<string>;
  1765. matched_rule?: string;
  1766. component?: EventGroupComponent;
  1767. config?: EventGroupingConfig;
  1768. };
  1769. export type SourceMapsArchive = {
  1770. id: number;
  1771. type: 'release';
  1772. name: string;
  1773. date: string;
  1774. fileCount: number;
  1775. };
  1776. export type Artifact = {
  1777. dateCreated: string;
  1778. dist: string | null;
  1779. id: string;
  1780. name: string;
  1781. sha1: string;
  1782. size: number;
  1783. headers: {'Content-Type': string};
  1784. };
  1785. export type EventGroupInfo = Record<EventGroupVariantKey, EventGroupVariant>;
  1786. // TODO(epurkhiser): objc and cocoa should almost definitely be moved into PlatformKey
  1787. export type PlatformType = PlatformKey | 'objc' | 'cocoa';
  1788. export type Frame = {
  1789. absPath: string | null;
  1790. colNo: number | null;
  1791. context: Array<[number, string]>;
  1792. errors: Array<any> | null;
  1793. filename: string | null;
  1794. function: string | null;
  1795. inApp: boolean;
  1796. instructionAddr: string | null;
  1797. lineNo: number | null;
  1798. module: string | null;
  1799. package: string | null;
  1800. platform: PlatformType | null;
  1801. rawFunction: string | null;
  1802. symbol: string | null;
  1803. symbolAddr: string | null;
  1804. trust: any | null;
  1805. vars: Record<string, any> | null;
  1806. symbolicatorStatus?: SymbolicatorStatus;
  1807. addrMode?: string;
  1808. origAbsPath?: string | null;
  1809. mapUrl?: string | null;
  1810. map?: string | null;
  1811. isSentinel?: boolean;
  1812. isPrefix?: boolean;
  1813. minGroupingLevel?: number;
  1814. };
  1815. export enum FrameBadge {
  1816. SENTINEL = 'sentinel',
  1817. PREFIX = 'prefix',
  1818. GROUPING = 'grouping',
  1819. }
  1820. /**
  1821. * Note used in Group Activity and Alerts for users to comment
  1822. */
  1823. export type Note = {
  1824. /**
  1825. * Note contents (markdown allowed)
  1826. */
  1827. text: string;
  1828. /**
  1829. * Array of [id, display string] tuples used for @-mentions
  1830. */
  1831. mentions: [string, string][];
  1832. };
  1833. export type FilesByRepository = {
  1834. [repoName: string]: {
  1835. authors?: {[email: string]: CommitAuthor};
  1836. types?: Set<string>;
  1837. };
  1838. };
  1839. export type ExceptionValue = {
  1840. type: string;
  1841. value: string;
  1842. threadId: number | null;
  1843. stacktrace: StacktraceType | null;
  1844. rawStacktrace: RawStacktrace;
  1845. mechanism: Mechanism | null;
  1846. module: string | null;
  1847. frames: Frame[] | null;
  1848. };
  1849. export type ExceptionType = {
  1850. excOmitted: any | null;
  1851. hasSystemFrames: boolean;
  1852. values?: Array<ExceptionValue>;
  1853. };
  1854. /**
  1855. * Identity is used in Account Identities for SocialAuths
  1856. */
  1857. export type Identity = {
  1858. id: string;
  1859. provider: IntegrationProvider;
  1860. providerLabel: string;
  1861. };
  1862. // taken from https://stackoverflow.com/questions/46634876/how-can-i-change-a-readonly-property-in-typescript
  1863. export type Writable<T> = {-readonly [K in keyof T]: T[K]};
  1864. export type InternetProtocol = {
  1865. id: string;
  1866. ipAddress: string;
  1867. lastSeen: string;
  1868. firstSeen: string;
  1869. countryCode: string | null;
  1870. regionCode: string | null;
  1871. };
  1872. /**
  1873. * XXX(ts): This actually all comes from getsentry. We should definitely
  1874. * refactor this into a more proper 'hook' mechanism in the future
  1875. */
  1876. export type AuthConfig = {
  1877. canRegister: boolean;
  1878. serverHostname: string;
  1879. hasNewsletter: boolean;
  1880. githubLoginLink: string;
  1881. vstsLoginLink: string;
  1882. googleLoginLink: string;
  1883. };
  1884. export type AuthProvider = {
  1885. key: string;
  1886. name: string;
  1887. requiredFeature: string;
  1888. disables2FA: boolean;
  1889. };
  1890. export type PromptActivity = {
  1891. snoozedTime?: number;
  1892. dismissedTime?: number;
  1893. };
  1894. export type ServerlessFunction = {
  1895. name: string;
  1896. runtime: string;
  1897. version: number;
  1898. outOfDate: boolean;
  1899. enabled: boolean;
  1900. };
  1901. /**
  1902. * Base type for series style API response
  1903. */
  1904. export type SeriesApi = {
  1905. intervals: string[];
  1906. groups: {
  1907. by: Record<string, string | number>;
  1908. totals: Record<string, number>;
  1909. series: Record<string, number[]>;
  1910. }[];
  1911. };
  1912. export type SessionApiResponse = SeriesApi & {
  1913. start: DateString;
  1914. end: DateString;
  1915. query: string;
  1916. intervals: string[];
  1917. groups: {
  1918. by: Record<string, string | number>;
  1919. totals: Record<string, number>;
  1920. series: Record<string, number[]>;
  1921. }[];
  1922. };
  1923. export enum SessionField {
  1924. SESSIONS = 'sum(session)',
  1925. USERS = 'count_unique(user)',
  1926. DURATION = 'p50(session.duration)',
  1927. }
  1928. export enum SessionStatus {
  1929. HEALTHY = 'healthy',
  1930. ABNORMAL = 'abnormal',
  1931. ERRORED = 'errored',
  1932. CRASHED = 'crashed',
  1933. }
  1934. export enum ReleaseComparisonChartType {
  1935. CRASH_FREE_USERS = 'crashFreeUsers',
  1936. HEALTHY_USERS = 'healthyUsers',
  1937. ABNORMAL_USERS = 'abnormalUsers',
  1938. ERRORED_USERS = 'erroredUsers',
  1939. CRASHED_USERS = 'crashedUsers',
  1940. CRASH_FREE_SESSIONS = 'crashFreeSessions',
  1941. HEALTHY_SESSIONS = 'healthySessions',
  1942. ABNORMAL_SESSIONS = 'abnormalSessions',
  1943. ERRORED_SESSIONS = 'erroredSessions',
  1944. CRASHED_SESSIONS = 'crashedSessions',
  1945. SESSION_COUNT = 'sessionCount',
  1946. USER_COUNT = 'userCount',
  1947. ERROR_COUNT = 'errorCount',
  1948. TRANSACTION_COUNT = 'transactionCount',
  1949. FAILURE_RATE = 'failureRate',
  1950. SESSION_DURATION = 'sessionDuration',
  1951. }
  1952. export enum HealthStatsPeriodOption {
  1953. AUTO = 'auto',
  1954. TWENTY_FOUR_HOURS = '24h',
  1955. }
  1956. export type IssueOwnership = {
  1957. raw: string;
  1958. fallthrough: boolean;
  1959. dateCreated: string;
  1960. lastUpdated: string;
  1961. isActive: boolean;
  1962. autoAssignment: boolean;
  1963. };
  1964. export type CodeOwner = {
  1965. id: string;
  1966. raw: string;
  1967. dateCreated: string;
  1968. dateUpdated: string;
  1969. provider: 'github' | 'gitlab';
  1970. codeMapping?: RepositoryProjectPathConfig;
  1971. codeMappingId: string;
  1972. ownershipSyntax?: string;
  1973. errors: {
  1974. missing_external_teams: string[];
  1975. missing_external_users: string[];
  1976. missing_user_emails: string[];
  1977. teams_without_access: string[];
  1978. users_without_access: string[];
  1979. };
  1980. };
  1981. export type KeyValueListData = {
  1982. key: string;
  1983. subject: string;
  1984. value?: React.ReactNode;
  1985. meta?: Meta;
  1986. subjectDataTestId?: string;
  1987. subjectIcon?: React.ReactNode;
  1988. }[];
  1989. export type ExternalActorMapping = {
  1990. id: string;
  1991. externalName: string;
  1992. userId?: string;
  1993. teamId?: string;
  1994. sentryName: string;
  1995. };
  1996. export type ExternalUser = {
  1997. id: string;
  1998. memberId: string;
  1999. externalName: string;
  2000. provider: string;
  2001. integrationId: string;
  2002. };
  2003. export type ExternalTeam = {
  2004. id: string;
  2005. teamId: string;
  2006. externalName: string;
  2007. provider: string;
  2008. integrationId: string;
  2009. };
  2010. export type CodeownersFile = {
  2011. raw: string;
  2012. filepath: string;
  2013. html_url: string;
  2014. };