index.tsx 49 KB

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