index.tsx 48 KB

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