Skip to content

Instantly share code, notes, and snippets.

@fredrikekelund
Created January 15, 2025 14:26
Show Gist options
  • Save fredrikekelund/89e483de7e8ac9fd46a8c2892f36fdff to your computer and use it in GitHub Desktop.
Save fredrikekelund/89e483de7e8ac9fd46a8c2892f36fdff to your computer and use it in GitHub Desktop.
Zustand store
import * as Sentry from '@sentry/electron/renderer';
import { create } from 'zustand';
import { DEFAULT_PHP_VERSION } from '../../vendor/wp-now/src/constants';
import { getIpcApi } from '../lib/get-ipc-api';
type WPCliItem = { name: string };
interface SiteState {
currentURL: string;
pluginList: string[];
themeList: string[];
numberOfSites: number;
phpVersion: string;
siteName: string;
isSiteLoadedDict: Record< string, boolean >;
}
interface ThemeState {
themeName: string;
isBlockTheme: boolean;
}
interface SystemState {
os: string;
availableEditors: string[];
wpVersion: string;
}
interface ChatState extends SiteState, ThemeState, SystemState {
getContextForApi: () => {
current_url: string;
number_of_sites: number;
wp_version: string;
php_version: string;
plugins: string[];
themes: string[];
current_theme: string;
is_block_theme: boolean;
ide: string[];
site_name: string;
os: string;
};
updateFromSite: ( site: SiteDetails ) => Promise< void >;
updateFromTheme: ( themeDetails: ThemeState ) => void;
}
const parseWpCliOutput = ( stdout: string ): string[] => {
try {
return JSON.parse( stdout )?.map( ( item: WPCliItem ) => item.name ) || [];
} catch ( error ) {
Sentry.captureException( error, { extra: { stdout } } );
return [];
}
};
const fetchPluginList = async ( siteId: string ): Promise< string[] > => {
const { stdout, stderr } = await getIpcApi().executeWPCLiInline( {
siteId,
args: 'plugin list --format=json --status=active',
skipPluginsAndThemes: true,
} );
return stderr ? [] : parseWpCliOutput( stdout );
};
const fetchThemeList = async ( siteId: string ): Promise< string[] > => {
const { stdout, stderr } = await getIpcApi().executeWPCLiInline( {
siteId,
args: 'theme list --format=json',
skipPluginsAndThemes: true,
} );
return stderr ? [] : parseWpCliOutput( stdout );
};
export const useChatStore = create< ChatState >()( ( set, get ) => ( {
// Initial state
currentURL: '',
pluginList: [],
themeList: [],
numberOfSites: 0,
themeName: '',
wpVersion: '',
phpVersion: DEFAULT_PHP_VERSION,
isBlockTheme: false,
os: window.appGlobals?.platform || '',
availableEditors: [],
siteName: '',
isSiteLoadedDict: {},
getContextForApi: () => ( {
current_url: get().currentURL,
number_of_sites: get().numberOfSites,
wp_version: get().wpVersion,
php_version: get().phpVersion,
plugins: get().pluginList,
themes: get().themeList,
current_theme: get().themeName,
is_block_theme: get().isBlockTheme,
ide: get().availableEditors,
site_name: get().siteName,
os: get().os,
} ),
updateFromSite: async ( site: SiteDetails ) => {
// Update site info and mark as loading
set( {
currentURL: `http://localhost:${ site.port }`,
phpVersion: site.phpVersion ?? DEFAULT_PHP_VERSION,
siteName: site.name,
isSiteLoadedDict: { ...get().isSiteLoadedDict, [ site.id ]: true },
} );
try {
const [ plugins, themes ] = await Promise.all( [
fetchPluginList( site.id ),
fetchThemeList( site.id ),
] );
set( { pluginList: plugins, themeList: themes } );
} catch ( error ) {
set( ( state ) => ( {
isSiteLoadedDict: { ...state.isSiteLoadedDict, [ site.id ]: false },
} ) );
}
},
updateFromTheme: ( themeDetails: ThemeState ) => {
set( themeDetails );
},
} ) );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment