Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 36 additions & 28 deletions packages/vue/src/pinia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,42 @@ type PiniaPlugin = (context: {
}) => void;

type SentryPiniaPluginOptions = {
attachPiniaState?: boolean;
addBreadcrumbs?: boolean;
actionTransformer?: (action: string) => any;
stateTransformer?: (state: Record<string, unknown>) => any;
attachPiniaState: boolean;
addBreadcrumbs: boolean;
actionTransformer: (action: string) => any;
stateTransformer: (state: Record<string, unknown>) => any;
};

export const createSentryPiniaPlugin: (options?: SentryPiniaPluginOptions) => PiniaPlugin = (
options: SentryPiniaPluginOptions = {
attachPiniaState: true,
addBreadcrumbs: true,
actionTransformer: action => action,
stateTransformer: state => state,
},
) => {
const plugin: PiniaPlugin = ({ store, pinia }) => {
const getAllStoreStates = (): Record<string, unknown> => {
const states: Record<string, unknown> = {};
const DEFAULT_PINIA_PLUGIN_OPTIONS: SentryPiniaPluginOptions = {
attachPiniaState: true,
addBreadcrumbs: true,
actionTransformer: action => action,
stateTransformer: state => state,
};

Object.keys(pinia.state.value).forEach(storeId => {
states[storeId] = pinia.state.value[storeId];
});
const getAllStoreStates = (
pinia: { state: Ref<Record<string, StateTree>> },
stateTransformer?: SentryPiniaPluginOptions['stateTransformer'],
): Record<string, unknown> => {
const states: Record<string, unknown> = {};

try {
Object.keys(pinia.state.value).forEach(storeId => {
states[storeId] = pinia.state.value[storeId];
});

return stateTransformer ? stateTransformer(states) : states;
} catch {
return states;
}
};

return states;
};
export const createSentryPiniaPlugin: (
userOptions?: Partial<SentryPiniaPluginOptions>,
) => PiniaPlugin = userOptions => {
const options: SentryPiniaPluginOptions = { ...DEFAULT_PINIA_PLUGIN_OPTIONS, ...userOptions };

const plugin: PiniaPlugin = ({ store, pinia }) => {
options.attachPiniaState !== false &&
getGlobalScope().addEventProcessor((event, hint) => {
try {
Expand All @@ -55,7 +66,7 @@ export const createSentryPiniaPlugin: (options?: SentryPiniaPluginOptions) => Pi
...(hint.attachments || []),
{
filename,
data: JSON.stringify(getAllStoreStates()),
data: JSON.stringify(getAllStoreStates(pinia, options.stateTransformer)),
},
];
}
Expand All @@ -68,9 +79,7 @@ export const createSentryPiniaPlugin: (options?: SentryPiniaPluginOptions) => Pi

store.$onAction(context => {
context.after(() => {
const transformedActionName = options.actionTransformer
? options.actionTransformer(context.name)
: context.name;
const transformedActionName = options.actionTransformer(context.name);

if (
typeof transformedActionName !== 'undefined' &&
Expand All @@ -85,16 +94,15 @@ export const createSentryPiniaPlugin: (options?: SentryPiniaPluginOptions) => Pi
}

/* Set latest state of all stores to scope */
const allStates = getAllStoreStates();
const transformedState = options.stateTransformer ? options.stateTransformer(allStates) : allStates;
const allStates = getAllStoreStates(pinia, options.stateTransformer);
const scope = getCurrentScope();
const currentState = scope.getScopeData().contexts.state;

if (typeof transformedState !== 'undefined' && transformedState !== null) {
if (typeof allStates !== 'undefined' && allStates !== null) {
const client = getClient();
const options = client?.getOptions();
const normalizationDepth = options?.normalizeDepth || 3; // default state normalization depth to 3
const piniaStateContext = { type: 'pinia', value: transformedState };
const piniaStateContext = { type: 'pinia', value: allStates };

const newState = {
...(currentState || {}),
Expand Down