index.tsx 46 KB

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