Skip to content
Merged
Changes from 4 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
19 changes: 12 additions & 7 deletions packages/vue/src/pinia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,20 @@ export const createSentryPiniaPlugin: (options?: SentryPiniaPluginOptions) => Pi
},
) => {
const plugin: PiniaPlugin = ({ store, pinia }) => {
const getAllStoreStates = (): Record<string, unknown> => {
const getAllStoreStates = (
stateTransformer?: SentryPiniaPluginOptions['stateTransformer'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m: The default options need to be destructured into the options object so that people can provide only a few of the options but still get the rest of the defaults.

// declare the type with no optional fields
type SentryPiniaPluginOptions = {
  attachPiniaState: boolean;
  addBreadcrumbs: boolean;
  actionTransformer: (action: string) => any;
  stateTransformer: (state: Record<string, unknown>) => any;
};

const DEFAULT_PINIA_PLUGIN_OPTIONS: SentryPiniaPluginOptions = {
  attachPiniaState: true,
  addBreadcrumbs: true,
  actionTransformer: action => action,
  stateTransformer: state => state,
}

// make sure user options are `Partial<SentryPiniaPluginOptions>` so that they can define
// a subset of options they want to override.
export const createSentryPiniaPlugin: = (userOptions: Partial<SentryPiniaPluginOptions> = {}): PiniaPlugin => {
  const { attachPiniaState, addBreadcrumbs, actionTransformer, stateTransformer } = { ...userOptions, ...DEFAULT_PINIA_PLUGIN_OPTIONS } as SentryPiniaPluginOptions;

This also means we don't need to pass in stateTransformer into getAllStoreStates, because it can grab it from the closure.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that stateTransformer could be grabbed from the closure here but I made it an argument of the function so it's more explicit that a stateTransformer is used when calling getAllStates. Otherwise it would be a weird side effect you only see when looking at the function code.

But good catch with the destructuring - right now it's either the users' object or the default one.

): Record<string, unknown> => {
const states: Record<string, unknown> = {};

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

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

options.attachPiniaState !== false &&
Expand All @@ -55,7 +61,7 @@ export const createSentryPiniaPlugin: (options?: SentryPiniaPluginOptions) => Pi
...(hint.attachments || []),
{
filename,
data: JSON.stringify(getAllStoreStates()),
data: JSON.stringify(getAllStoreStates(options.stateTransformer)),
},
];
}
Expand Down Expand Up @@ -85,16 +91,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(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
Loading