@oxyhq/services
Version:
177 lines (165 loc) • 5.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createGenericMutation = createGenericMutation;
exports.createProfileMutation = createProfileMutation;
var _queryKeys = require("../queries/queryKeys.js");
var _sonner = require("../../../lib/sonner");
var _authStore = require("../../stores/authStore.js");
/**
* Mutation Factory - Creates standardized mutations with optimistic updates
*
* This factory reduces boilerplate code for mutations that follow the common pattern:
* 1. Cancel outgoing queries
* 2. Snapshot previous data
* 3. Apply optimistic update
* 4. On error: rollback and show toast
* 5. On success: update cache, stores, and invalidate queries
*/
/**
* Configuration for creating a standard profile mutation
*/
/**
* Creates a standard profile mutation with optimistic updates
*
* @example
* ```ts
* const updateProfile = createProfileMutation({
* mutationFn: (updates) => oxyServices.updateProfile(updates),
* optimisticUpdate: (user, updates) => updates,
* errorMessage: 'Failed to update profile',
* });
* ```
*/
function createProfileMutation(config, queryClient, activeSessionId) {
const {
mutationFn,
cancelQueryKeys = [],
optimisticUpdate,
errorMessage = 'Operation failed',
successMessage,
updateAuthStore = true,
invalidateUserQueries: shouldInvalidateUserQueries = true,
invalidateAccountQueries: shouldInvalidateAccountQueries = true,
onSuccess: customOnSuccess
} = config;
return {
mutationFn,
onMutate: async variables => {
// Cancel queries that might conflict
await queryClient.cancelQueries({
queryKey: _queryKeys.queryKeys.accounts.current()
});
for (const key of cancelQueryKeys) {
await queryClient.cancelQueries({
queryKey: key
});
}
// Snapshot previous user data
const previousUser = queryClient.getQueryData(_queryKeys.queryKeys.accounts.current());
// Apply optimistic update if provided
if (previousUser && optimisticUpdate) {
const updates = optimisticUpdate(previousUser, variables);
const optimisticUser = {
...previousUser,
...updates
};
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), optimisticUser);
if (activeSessionId) {
queryClient.setQueryData(_queryKeys.queryKeys.users.profile(activeSessionId), optimisticUser);
}
}
return {
previousUser
};
},
onError: (error, _variables, context) => {
// Rollback optimistic update
if (context?.previousUser) {
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), context.previousUser);
if (activeSessionId) {
queryClient.setQueryData(_queryKeys.queryKeys.users.profile(activeSessionId), context.previousUser);
}
}
// Show error toast
const message = typeof errorMessage === 'function' ? errorMessage(error) : error instanceof Error ? error.message : errorMessage;
_sonner.toast.error(message);
},
onSuccess: (data, variables) => {
// Update cache with server response
queryClient.setQueryData(_queryKeys.queryKeys.accounts.current(), data);
if (activeSessionId) {
queryClient.setQueryData(_queryKeys.queryKeys.users.profile(activeSessionId), data);
}
// Update authStore for immediate UI updates
if (updateAuthStore) {
_authStore.useAuthStore.getState().setUser(data);
}
// Invalidate related queries
if (shouldInvalidateUserQueries) {
(0, _queryKeys.invalidateUserQueries)(queryClient);
}
if (shouldInvalidateAccountQueries) {
(0, _queryKeys.invalidateAccountQueries)(queryClient);
}
// Show success toast if configured
if (successMessage) {
_sonner.toast.success(successMessage);
}
// Call custom onSuccess handler
if (customOnSuccess) {
customOnSuccess(data, variables, queryClient);
}
}
};
}
/**
* Configuration for creating a generic mutation (non-profile)
*/
/**
* Creates a generic mutation with optimistic updates
*/
function createGenericMutation(config, queryClient) {
const {
mutationFn,
queryKey,
optimisticData,
errorMessage = 'Operation failed',
successMessage,
invalidateQueries = []
} = config;
return {
mutationFn,
onMutate: async variables => {
await queryClient.cancelQueries({
queryKey
});
const previous = queryClient.getQueryData(queryKey);
if (optimisticData) {
queryClient.setQueryData(queryKey, optimisticData(previous, variables));
}
return {
previous
};
},
onError: (error, _variables, context) => {
if (context?.previous !== undefined) {
queryClient.setQueryData(queryKey, context.previous);
}
_sonner.toast.error(error instanceof Error ? error.message : errorMessage);
},
onSuccess: data => {
queryClient.setQueryData(queryKey, data);
for (const key of invalidateQueries) {
queryClient.invalidateQueries({
queryKey: key
});
}
if (successMessage) {
_sonner.toast.success(successMessage);
}
}
};
}
//# sourceMappingURL=mutationFactory.js.map