Skip to content

Commit 7383f8a

Browse files
authored
ref(feedback): Refactor Feedback types into @sentry/types and reduce the exported surface area (#11355)
You can read this commit-by-commit to watch the refactor unfold The situation is: after #11342 is merged, all the code inside each of the `packages/feedback/src/[core|modal|screenshot]` will be split up into separate integrations. These integrations can't share the same `src/types/*.ts` definitions anymore. Therefore type definitions will need to live in @sentry/types instead. This PR moves all the types, and since they'll be public now in that package, i refactored things to reduce the public surface area and improve names where possible. The only non-type changes in here are where we move `createDialog.ts` and `createInput.ts` into their respective `integration.ts` files, no code changes at all. Related to #11435
1 parent f7db230 commit 7383f8a

25 files changed

+346
-362
lines changed

packages/feedback/src/core/createMainStyles.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import type { FeedbackInternalOptions } from '@sentry/types';
12
import { DOCUMENT } from '../constants';
2-
import type { FeedbackTheme, FeedbackThemes } from '../types';
33

4-
function getThemedCssVariables(theme: FeedbackTheme): string {
4+
function getThemedCssVariables(theme: FeedbackInternalOptions['themeLight']): string {
55
return `
66
--background: ${theme.background};
77
--background-hover: ${theme.backgroundHover};
@@ -39,7 +39,10 @@ function getThemedCssVariables(theme: FeedbackTheme): string {
3939
/**
4040
* Creates <style> element for widget actor (button that opens the dialog)
4141
*/
42-
export function createMainStyles(colorScheme: 'system' | 'dark' | 'light', themes: FeedbackThemes): HTMLStyleElement {
42+
export function createMainStyles(
43+
colorScheme: 'system' | 'dark' | 'light',
44+
themes: Pick<FeedbackInternalOptions, 'themeLight' | 'themeDark'>,
45+
): HTMLStyleElement {
4346
const style = DOCUMENT.createElement('style');
4447
style.textContent = `
4548
:host {

packages/feedback/src/core/integration.ts

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { getClient } from '@sentry/core';
2-
import type { Integration, IntegrationFn } from '@sentry/types';
2+
import type {
3+
FeedbackDialog,
4+
FeedbackInternalOptions,
5+
FeedbackModalIntegration,
6+
FeedbackScreenshotIntegration,
7+
IntegrationFn,
8+
} from '@sentry/types';
39
import { isBrowser, logger } from '@sentry/utils';
410
import {
511
ACTOR_LABEL,
@@ -17,34 +23,16 @@ import {
1723
SUBMIT_BUTTON_LABEL,
1824
SUCCESS_MESSAGE_TEXT,
1925
} from '../constants';
20-
import type { IFeedbackModalIntegration } from '../modal/integration';
21-
import type { IFeedbackScreenshotIntegration } from '../screenshot/integration';
22-
import type {
23-
Dialog,
24-
FeedbackInternalOptions,
25-
OptionalFeedbackConfiguration,
26-
OverrideFeedbackConfiguration,
27-
} from '../types';
2826
import { DEBUG_BUILD } from '../util/debug-build';
2927
import { isScreenshotSupported } from '../util/isScreenshotSupported';
3028
import { mergeOptions } from '../util/mergeOptions';
3129
import { Actor } from './components/Actor';
3230
import { createMainStyles } from './createMainStyles';
3331
import { sendFeedback } from './sendFeedback';
32+
import type { OptionalFeedbackConfiguration, OverrideFeedbackConfiguration } from './types';
3433

3534
type Unsubscribe = () => void;
3635

37-
interface PublicFeedbackIntegration {
38-
attachTo: (el: Element | string, optionOverrides: OverrideFeedbackConfiguration) => () => void;
39-
createWidget: (optionOverrides: OverrideFeedbackConfiguration & { shouldCreateActor?: boolean }) => Promise<Dialog>;
40-
getWidget: () => Dialog | null;
41-
remove: () => void;
42-
openDialog: () => void;
43-
closeDialog: () => void;
44-
removeWidget: () => void;
45-
}
46-
export type IFeedbackIntegration = Integration & PublicFeedbackIntegration;
47-
4836
/**
4937
* Allow users to capture user feedback and send it to Sentry.
5038
*/
@@ -148,13 +136,13 @@ export const feedbackIntegration = (({
148136
return _shadow as ShadowRoot;
149137
};
150138

151-
const _loadAndRenderDialog = async (options: FeedbackInternalOptions): Promise<Dialog> => {
139+
const _loadAndRenderDialog = async (options: FeedbackInternalOptions): Promise<FeedbackDialog> => {
152140
const client = getClient(); // TODO: getClient<BrowserClient>()
153141
if (!client) {
154142
throw new Error('Sentry Client is not initialized correctly');
155143
}
156-
const modalIntegration = client.getIntegrationByName<IFeedbackModalIntegration>('FeedbackModal');
157-
const screenshotIntegration = client.getIntegrationByName<IFeedbackScreenshotIntegration>('FeedbackScreenshot');
144+
const modalIntegration = client.getIntegrationByName<FeedbackModalIntegration>('FeedbackModal');
145+
const screenshotIntegration = client.getIntegrationByName<FeedbackScreenshotIntegration>('FeedbackScreenshot');
158146
const screenshotIsSupported = isScreenshotSupported();
159147

160148
// START TEMP: Error messages
@@ -196,7 +184,7 @@ export const feedbackIntegration = (({
196184
throw new Error('Unable to attach to target element');
197185
}
198186

199-
let dialog: Dialog | null = null;
187+
let dialog: FeedbackDialog | null = null;
200188
const handleClick = async (): Promise<void> => {
201189
if (!dialog) {
202190
dialog = await _loadAndRenderDialog({
@@ -264,7 +252,7 @@ export const feedbackIntegration = (({
264252
/**
265253
* Creates a new widget. Accepts partial options to override any options passed to constructor.
266254
*/
267-
async createWidget(optionOverrides: OverrideFeedbackConfiguration = {}): Promise<Dialog> {
255+
async createWidget(optionOverrides: OverrideFeedbackConfiguration = {}): Promise<FeedbackDialog> {
268256
return _loadAndRenderDialog(mergeOptions(_options, optionOverrides));
269257
},
270258

packages/feedback/src/core/sendFeedback.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
import { createAttachmentEnvelope, createEventEnvelope, getClient, withScope } from '@sentry/core';
2-
import type { FeedbackEvent, TransportMakeRequestResponse } from '@sentry/types';
2+
import type { FeedbackEvent, SendFeedback, SendFeedbackParams } from '@sentry/types';
33
import { getLocationHref } from '@sentry/utils';
44
import { FEEDBACK_API_SOURCE, FEEDBACK_WIDGET_SOURCE } from '../constants';
5-
import type { SendFeedbackOptions, SendFeedbackParams } from '../types';
65
import { prepareFeedbackEvent } from '../util/prepareFeedbackEvent';
76

87
/**
98
* Public API to send a Feedback item to Sentry
109
*/
11-
export async function sendFeedback(
10+
export const sendFeedback: SendFeedback = (
1211
{ name, email, message, attachments, source = FEEDBACK_API_SOURCE, url = getLocationHref() }: SendFeedbackParams,
13-
{ includeReplay = true }: SendFeedbackOptions = {},
14-
): Promise<TransportMakeRequestResponse> {
12+
{ includeReplay = true } = {},
13+
) => {
1514
if (!message) {
1615
throw new Error('Unable to submit feedback with empty message');
1716
}
@@ -97,7 +96,7 @@ export async function sendFeedback(
9796
throw error;
9897
}
9998
});
100-
}
99+
};
101100

102101
/*
103102
* For reference, the fully built event looks something like this:

packages/feedback/src/core/types.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { FeedbackInternalOptions } from '@sentry/types';
2+
3+
/**
4+
* Partial configuration that overrides default configuration values
5+
*
6+
* This is the config that gets passed into the integration constructor
7+
*/
8+
export interface OptionalFeedbackConfiguration
9+
extends Omit<Partial<FeedbackInternalOptions>, 'themeLight' | 'themeDark'> {
10+
themeLight?: Partial<FeedbackInternalOptions['themeLight']>;
11+
themeDark?: Partial<FeedbackInternalOptions['themeLight']>;
12+
}
13+
14+
/**
15+
* Partial configuration that overrides default configuration values
16+
*
17+
* This is the config that gets passed into the integration constructor
18+
*/
19+
export type OverrideFeedbackConfiguration = Omit<Partial<FeedbackInternalOptions>, 'themeLight' | 'themeDark'>;

packages/feedback/src/index.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,3 @@ export { feedbackIntegration } from './core/integration';
33
export { feedbackModalIntegration } from './modal/integration';
44
export { getFeedback } from './core/getFeedback';
55
export { feedbackScreenshotIntegration } from './screenshot/integration';
6-
7-
export type { OptionalFeedbackConfiguration } from './types';
8-
export type { IFeedbackIntegration } from './core/integration';

packages/feedback/src/modal/components/DialogContainer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
import type { FeedbackFormData } from '@sentry/types';
12
// biome-ignore lint/nursery/noUnusedImports: reason
23
import { Fragment, h } from 'preact'; // eslint-disable-line @typescript-eslint/no-unused-vars
34
import type { VNode } from 'preact';
45
import { useCallback, useMemo, useState } from 'preact/hooks';
56
import { SUCCESS_MESSAGE_TIMEOUT } from '../../constants';
6-
import type { FeedbackFormData } from '../../types';
77
import { DialogContent } from './DialogContent';
88
import { DialogHeader } from './DialogHeader';
99
import type { Props as HeaderProps } from './DialogHeader';

packages/feedback/src/modal/components/DialogHeader.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import type { FeedbackInternalOptions } from '@sentry/types';
12
// biome-ignore lint/nursery/noUnusedImports: reason
23
import { h } from 'preact'; // eslint-disable-line @typescript-eslint/no-unused-vars
34
import type { VNode } from 'preact';
45
import { useMemo } from 'preact/hooks';
5-
import type { FeedbackInternalOptions } from '../../types';
66
import type { Props as LogoProps } from './SentryLogo';
77
import { SentryLogo } from './SentryLogo';
88

packages/feedback/src/modal/components/Form.tsx

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1+
import type {
2+
FeedbackFormData,
3+
FeedbackInternalOptions,
4+
FeedbackScreenshotIntegration,
5+
SendFeedback,
6+
} from '@sentry/types';
17
import { logger } from '@sentry/utils';
28
// biome-ignore lint/nursery/noUnusedImports: reason
39
import { h } from 'preact'; // eslint-disable-line @typescript-eslint/no-unused-vars
410
import type { JSX, VNode } from 'preact';
511
import { useCallback, useState } from 'preact/hooks';
612
import { FEEDBACK_WIDGET_SOURCE } from '../../constants';
7-
import type {
8-
FeedbackFormData,
9-
FeedbackInternalOptions,
10-
ScreenshotInput,
11-
SendFeedbackOptions,
12-
SendFeedbackParams,
13-
} from '../../types';
1413
import { DEBUG_BUILD } from '../../util/debug-build';
1514
import { getMissingFields } from '../../util/validate';
1615

@@ -34,10 +33,10 @@ export interface Props
3433
defaultEmail: string;
3534
defaultName: string;
3635
onFormClose: () => void;
37-
onSubmit: (data: SendFeedbackParams, options?: SendFeedbackOptions) => void;
36+
onSubmit: SendFeedback;
3837
onSubmitSuccess: (data: FeedbackFormData) => void;
3938
onSubmitError: (error: Error) => void;
40-
screenshotInput: ScreenshotInput | undefined;
39+
screenshotInput: ReturnType<FeedbackScreenshotIntegration['createInput']> | undefined;
4140
}
4241

4342
function retrieveStringValue(formData: FormData, key: string): string {
@@ -74,8 +73,8 @@ export function Form({
7473
const [error, setError] = useState<null | string>(null);
7574

7675
const [showScreenshotInput, setShowScreenshotInput] = useState(false);
77-
const ScreenshotInput = screenshotInput && screenshotInput.input;
78-
const includeScreenshotValue = ScreenshotInput && showScreenshotInput;
76+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
77+
const ScreenshotInputComponent: any = screenshotInput && screenshotInput.input;
7978

8079
const [screenshotError, setScreenshotError] = useState<null | Error>(null);
8180
const onScreenshotError = useCallback((error: Error) => {
@@ -112,7 +111,7 @@ export function Form({
112111
return;
113112
}
114113
const formData = new FormData(e.target);
115-
const attachment = await (includeScreenshotValue ? screenshotInput.value() : undefined);
114+
const attachment = await (screenshotInput && showScreenshotInput ? screenshotInput.value() : undefined);
116115
const data: FeedbackFormData = {
117116
name: retrieveStringValue(formData, 'name'),
118117
email: retrieveStringValue(formData, 'email'),
@@ -134,12 +133,14 @@ export function Form({
134133
// pass
135134
}
136135
},
137-
[includeScreenshotValue, onSubmitSuccess, onSubmitError],
136+
[screenshotInput && showScreenshotInput, onSubmitSuccess, onSubmitError],
138137
);
139138

140139
return (
141140
<form class="form" onSubmit={handleSubmit}>
142-
{includeScreenshotValue ? <ScreenshotInput onError={onScreenshotError} /> : null}
141+
{ScreenshotInputComponent && showScreenshotInput ? (
142+
<ScreenshotInputComponent onError={onScreenshotError} />
143+
) : null}
143144

144145
<div class="form__right">
145146
<div class="form__top">
@@ -192,7 +193,7 @@ export function Form({
192193
/>
193194
</label>
194195

195-
{ScreenshotInput ? (
196+
{ScreenshotInputComponent ? (
196197
<label for="screenshot" class="form__label">
197198
<span class="form__label__text">Screenshot</span>
198199

packages/feedback/src/modal/components/SentryLogo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
import type { FeedbackInternalOptions } from '@sentry/types';
12
import { DOCUMENT } from '../../constants';
2-
import type { FeedbackInternalOptions } from '../../types';
33
import { setAttributesNS } from '../../util/setAttributesNS';
44

55
const XMLNS = 'http://www.w3.org/2000/svg';

packages/feedback/src/modal/createDialog.tsx

Lines changed: 0 additions & 95 deletions
This file was deleted.

packages/feedback/src/modal/integration.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)