fix: close marketplace client review findings
This commit is contained in:
@@ -2,6 +2,7 @@ import { createStore, type StoreApi } from 'zustand';
|
||||
import { useStore } from 'zustand';
|
||||
import {
|
||||
acquireMarketplacePlugin,
|
||||
installBetaMarketplacePlugin,
|
||||
installMarketplacePlugin,
|
||||
readMarketplaceCatalog,
|
||||
readMarketplaceDetail,
|
||||
@@ -26,6 +27,7 @@ export type PluginMarketplaceDependencies = {
|
||||
acquire(pluginId: string): Promise<MarketplaceLibraryProjection>;
|
||||
remove(pluginId: string): Promise<MarketplaceLibraryProjection>;
|
||||
install(pluginId: string): Promise<MarketplaceInstallation>;
|
||||
installBeta(pluginId: string): Promise<MarketplaceInstallation>;
|
||||
update(pluginId: string): Promise<MarketplaceInstallation>;
|
||||
uninstall(pluginId: string): Promise<MarketplaceInstallation>;
|
||||
};
|
||||
@@ -50,6 +52,7 @@ export type PluginMarketplaceState = {
|
||||
acquire(pluginId: string): Promise<void>;
|
||||
remove(pluginId: string): Promise<void>;
|
||||
install(pluginId: string): Promise<void>;
|
||||
installBeta(pluginId: string): Promise<void>;
|
||||
update(pluginId: string): Promise<void>;
|
||||
uninstall(pluginId: string): Promise<void>;
|
||||
};
|
||||
@@ -61,6 +64,7 @@ const defaults: PluginMarketplaceDependencies = {
|
||||
acquire: acquireMarketplacePlugin,
|
||||
remove: removeMarketplacePlugin,
|
||||
install: installMarketplacePlugin,
|
||||
installBeta: installBetaMarketplacePlugin,
|
||||
update: updateMarketplacePlugin,
|
||||
uninstall: uninstallMarketplacePlugin,
|
||||
};
|
||||
@@ -68,11 +72,13 @@ const defaults: PluginMarketplaceDependencies = {
|
||||
function message(error: unknown): string {
|
||||
const base = error instanceof Error ? error.message : String(error);
|
||||
if (!error || typeof error !== 'object') return base;
|
||||
const errorCode = 'code' in error && typeof error.code === 'string' ? error.code : null;
|
||||
const details = 'details' in error && error.details && typeof error.details === 'object'
|
||||
? error.details as Record<string, unknown>
|
||||
: null;
|
||||
const backendCode = details?.backendCode;
|
||||
return typeof backendCode === 'string' ? `${backendCode}: ${base}` : base;
|
||||
const prefixed = typeof backendCode === 'string' ? `${backendCode}: ${base}` : base;
|
||||
return errorCode && !prefixed.includes(errorCode) ? `${errorCode}: ${prefixed}` : prefixed;
|
||||
}
|
||||
|
||||
function installationMap(items: readonly MarketplaceInstallation[]): Record<string, MarketplaceInstallation> {
|
||||
@@ -86,6 +92,7 @@ export function createPluginMarketplaceStore(
|
||||
let scopeGeneration = 0;
|
||||
let catalogGeneration = 0;
|
||||
let libraryMutationEpoch = 0;
|
||||
let libraryReadGeneration = 0;
|
||||
|
||||
return createStore<PluginMarketplaceState>((set, get) => {
|
||||
const pending = async <T>(key: string, operation: () => Promise<T>): Promise<T> => {
|
||||
@@ -109,9 +116,11 @@ export function createPluginMarketplaceStore(
|
||||
const generation = scopeGeneration;
|
||||
const accountKey = get().accountKey;
|
||||
if (!accountKey) throw new Error('请先登录后管理我的插件');
|
||||
const mutationEpoch = ++libraryMutationEpoch;
|
||||
try {
|
||||
const projection = await action(pluginId);
|
||||
if (generation !== scopeGeneration || get().accountKey !== accountKey) return;
|
||||
if (generation !== scopeGeneration || get().accountKey !== accountKey
|
||||
|| mutationEpoch !== libraryMutationEpoch) return;
|
||||
libraryMutationEpoch += 1;
|
||||
set({
|
||||
library: projection.library,
|
||||
@@ -120,7 +129,8 @@ export function createPluginMarketplaceStore(
|
||||
libraryError: null,
|
||||
});
|
||||
} catch (error) {
|
||||
if (generation === scopeGeneration && get().accountKey === accountKey) {
|
||||
if (generation === scopeGeneration && get().accountKey === accountKey
|
||||
&& mutationEpoch === libraryMutationEpoch) {
|
||||
set({ libraryError: message(error) });
|
||||
}
|
||||
throw error;
|
||||
@@ -135,9 +145,11 @@ export function createPluginMarketplaceStore(
|
||||
const generation = scopeGeneration;
|
||||
const accountKey = get().accountKey;
|
||||
if (!accountKey) throw new Error('请先登录后管理设备插件');
|
||||
const mutationEpoch = ++libraryMutationEpoch;
|
||||
try {
|
||||
const result = await action(pluginId);
|
||||
if (generation !== scopeGeneration || get().accountKey !== accountKey) return;
|
||||
if (generation !== scopeGeneration || get().accountKey !== accountKey
|
||||
|| mutationEpoch !== libraryMutationEpoch) return;
|
||||
libraryMutationEpoch += 1;
|
||||
set((state) => {
|
||||
const installations = { ...state.installations };
|
||||
@@ -146,8 +158,26 @@ export function createPluginMarketplaceStore(
|
||||
return { installations, libraryError: null };
|
||||
});
|
||||
} catch (error) {
|
||||
if (generation === scopeGeneration && get().accountKey === accountKey) {
|
||||
set({ libraryError: message(error) });
|
||||
if (generation === scopeGeneration && get().accountKey === accountKey
|
||||
&& mutationEpoch === libraryMutationEpoch) {
|
||||
const reason = message(error);
|
||||
set((state) => ({
|
||||
installations: {
|
||||
...state.installations,
|
||||
[pluginId]: {
|
||||
status: 'unavailable',
|
||||
pluginId,
|
||||
...(state.installations[pluginId]?.releaseId
|
||||
? { releaseId: state.installations[pluginId].releaseId }
|
||||
: {}),
|
||||
...(state.installations[pluginId]?.version
|
||||
? { version: state.installations[pluginId].version }
|
||||
: {}),
|
||||
reason,
|
||||
},
|
||||
},
|
||||
libraryError: reason,
|
||||
}));
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
@@ -169,7 +199,8 @@ export function createPluginMarketplaceStore(
|
||||
activateAccount(accountKey) {
|
||||
if (get().accountKey === accountKey) return;
|
||||
scopeGeneration += 1;
|
||||
libraryMutationEpoch = 0;
|
||||
libraryReadGeneration += 1;
|
||||
libraryMutationEpoch += 1;
|
||||
set({
|
||||
accountKey,
|
||||
library: null,
|
||||
@@ -211,6 +242,7 @@ export function createPluginMarketplaceStore(
|
||||
}
|
||||
},
|
||||
async loadLibrary() {
|
||||
const readGeneration = ++libraryReadGeneration;
|
||||
const generation = scopeGeneration;
|
||||
const accountKey = get().accountKey;
|
||||
const mutationEpoch = libraryMutationEpoch;
|
||||
@@ -222,6 +254,7 @@ export function createPluginMarketplaceStore(
|
||||
try {
|
||||
const projection = await deps.readLibrary();
|
||||
if (generation === scopeGeneration && get().accountKey === accountKey
|
||||
&& readGeneration === libraryReadGeneration
|
||||
&& mutationEpoch === libraryMutationEpoch) {
|
||||
set({
|
||||
library: projection.library,
|
||||
@@ -231,7 +264,9 @@ export function createPluginMarketplaceStore(
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
if (generation === scopeGeneration && get().accountKey === accountKey) {
|
||||
if (generation === scopeGeneration && get().accountKey === accountKey
|
||||
&& readGeneration === libraryReadGeneration
|
||||
&& mutationEpoch === libraryMutationEpoch) {
|
||||
set({ libraryState: 'error', libraryError: message(error) });
|
||||
}
|
||||
throw error;
|
||||
@@ -240,6 +275,7 @@ export function createPluginMarketplaceStore(
|
||||
acquire: (pluginId) => libraryAction(`acquire:${pluginId}`, pluginId, deps.acquire),
|
||||
remove: (pluginId) => libraryAction(`remove:${pluginId}`, pluginId, deps.remove),
|
||||
install: (pluginId) => installAction(`install:${pluginId}`, pluginId, deps.install),
|
||||
installBeta: (pluginId) => installAction(`install-beta:${pluginId}`, pluginId, deps.installBeta),
|
||||
update: (pluginId) => installAction(`update:${pluginId}`, pluginId, deps.update),
|
||||
uninstall: (pluginId) => installAction(`uninstall:${pluginId}`, pluginId, deps.uninstall),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user