index.tsx 44 KB

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