feat: custom commands (#162)
This commit is contained in:
@@ -23,8 +23,18 @@ export async function listWorkspaces(options?: ApiRequestOptions) {
|
||||
}
|
||||
|
||||
// Repository operations
|
||||
export async function listRepositories(workspaceId: string, options?: ApiRequestOptions) {
|
||||
return fetchJson<ListRepositoriesResponse>(`/api/v1/workspaces/${workspaceId}/repositories`, options);
|
||||
export async function listRepositories(
|
||||
workspaceId: string,
|
||||
params?: { includeScripts?: boolean },
|
||||
options?: ApiRequestOptions
|
||||
) {
|
||||
const searchParams = new URLSearchParams();
|
||||
if (params?.includeScripts) {
|
||||
searchParams.set('include_scripts', 'true');
|
||||
}
|
||||
const queryString = searchParams.toString();
|
||||
const url = `/api/v1/workspaces/${workspaceId}/repositories${queryString ? `?${queryString}` : ''}`;
|
||||
return fetchJson<ListRepositoriesResponse>(url, options);
|
||||
}
|
||||
|
||||
export async function listRepositoryBranches(repositoryId: string, options?: ApiRequestOptions) {
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };
|
||||
|
||||
// Session Storage helpers (cleared when browser tab closes)
|
||||
export function getSessionStorage<T extends JsonValue>(key: string, fallback: T): T {
|
||||
if (typeof window === 'undefined') return fallback;
|
||||
try {
|
||||
const raw = window.sessionStorage.getItem(key);
|
||||
if (!raw) return fallback;
|
||||
return JSON.parse(raw) as T;
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
export function setSessionStorage<T extends JsonValue>(key: string, value: T): void {
|
||||
if (typeof window === 'undefined') return;
|
||||
try {
|
||||
window.sessionStorage.setItem(key, JSON.stringify(value));
|
||||
} catch {
|
||||
// Ignore write failures (storage full, blocked, etc.)
|
||||
}
|
||||
}
|
||||
|
||||
// Local Storage helpers (persists across browser sessions)
|
||||
export function getLocalStorage<T extends JsonValue>(key: string, fallback: T): T {
|
||||
if (typeof window === 'undefined') return fallback;
|
||||
try {
|
||||
|
||||
@@ -27,7 +27,7 @@ export type { UISlice, UISliceState, UISliceActions } from './ui/types';
|
||||
|
||||
// Re-export commonly used types from each domain
|
||||
export type { KanbanState, BoardState, TaskState } from './kanban/types';
|
||||
export type { WorkspaceState, RepositoriesState, RepositoryBranchesState } from './workspace/types';
|
||||
export type { WorkspaceState, RepositoriesState, RepositoryBranchesState, RepositoryScriptsState } from './workspace/types';
|
||||
export type {
|
||||
ExecutorsState,
|
||||
EnvironmentsState,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Repository, Branch } from '@/lib/types/http';
|
||||
import type { Repository, Branch, RepositoryScript } from '@/lib/types/http';
|
||||
|
||||
export type WorkspaceState = {
|
||||
items: Array<{
|
||||
@@ -27,10 +27,17 @@ export type RepositoryBranchesState = {
|
||||
loadedByRepositoryId: Record<string, boolean>;
|
||||
};
|
||||
|
||||
export type RepositoryScriptsState = {
|
||||
itemsByRepositoryId: Record<string, RepositoryScript[]>;
|
||||
loadingByRepositoryId: Record<string, boolean>;
|
||||
loadedByRepositoryId: Record<string, boolean>;
|
||||
};
|
||||
|
||||
export type WorkspaceSliceState = {
|
||||
workspaces: WorkspaceState;
|
||||
repositories: RepositoriesState;
|
||||
repositoryBranches: RepositoryBranchesState;
|
||||
repositoryScripts: RepositoryScriptsState;
|
||||
};
|
||||
|
||||
export type WorkspaceSliceActions = {
|
||||
@@ -40,6 +47,8 @@ export type WorkspaceSliceActions = {
|
||||
setRepositoriesLoading: (workspaceId: string, loading: boolean) => void;
|
||||
setRepositoryBranches: (repositoryId: string, branches: Branch[]) => void;
|
||||
setRepositoryBranchesLoading: (repositoryId: string, loading: boolean) => void;
|
||||
setRepositoryScripts: (repositoryId: string, scripts: RepositoryScript[]) => void;
|
||||
setRepositoryScriptsLoading: (repositoryId: string, loading: boolean) => void;
|
||||
};
|
||||
|
||||
export type WorkspaceSlice = WorkspaceSliceState & WorkspaceSliceActions;
|
||||
|
||||
@@ -5,6 +5,7 @@ export const defaultWorkspaceState: WorkspaceSliceState = {
|
||||
workspaces: { items: [], activeId: null },
|
||||
repositories: { itemsByWorkspaceId: {}, loadingByWorkspaceId: {}, loadedByWorkspaceId: {} },
|
||||
repositoryBranches: { itemsByRepositoryId: {}, loadingByRepositoryId: {}, loadedByRepositoryId: {} },
|
||||
repositoryScripts: { itemsByRepositoryId: {}, loadingByRepositoryId: {}, loadedByRepositoryId: {} },
|
||||
};
|
||||
|
||||
export const createWorkspaceSlice: StateCreator<
|
||||
@@ -49,4 +50,14 @@ export const createWorkspaceSlice: StateCreator<
|
||||
set((draft) => {
|
||||
draft.repositoryBranches.loadingByRepositoryId[repositoryId] = loading;
|
||||
}),
|
||||
setRepositoryScripts: (repositoryId, scripts) =>
|
||||
set((draft) => {
|
||||
draft.repositoryScripts.itemsByRepositoryId[repositoryId] = scripts;
|
||||
draft.repositoryScripts.loadingByRepositoryId[repositoryId] = false;
|
||||
draft.repositoryScripts.loadedByRepositoryId[repositoryId] = true;
|
||||
}),
|
||||
setRepositoryScriptsLoading: (repositoryId, loading) =>
|
||||
set((draft) => {
|
||||
draft.repositoryScripts.loadingByRepositoryId[repositoryId] = loading;
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createStore } from 'zustand/vanilla';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { hydrateState, type HydrationOptions } from './hydration/hydrator';
|
||||
import type { Repository, Branch, Message, Turn, TaskSession } from '@/lib/types/http';
|
||||
import type { Repository, Branch, RepositoryScript, Message, Turn, TaskSession } from '@/lib/types/http';
|
||||
import {
|
||||
createKanbanSlice,
|
||||
createWorkspaceSlice,
|
||||
@@ -49,6 +49,7 @@ export type {
|
||||
WorkspaceState,
|
||||
RepositoriesState,
|
||||
RepositoryBranchesState,
|
||||
RepositoryScriptsState,
|
||||
ExecutorsState,
|
||||
EnvironmentsState,
|
||||
SettingsAgentsState,
|
||||
@@ -103,6 +104,7 @@ export type AppState = {
|
||||
workspaces: typeof defaultWorkspaceState['workspaces'];
|
||||
repositories: typeof defaultWorkspaceState['repositories'];
|
||||
repositoryBranches: typeof defaultWorkspaceState['repositoryBranches'];
|
||||
repositoryScripts: typeof defaultWorkspaceState['repositoryScripts'];
|
||||
|
||||
// Settings slice
|
||||
executors: typeof defaultSettingsState['executors'];
|
||||
@@ -164,6 +166,8 @@ export type AppState = {
|
||||
setRepositoriesLoading: (workspaceId: string, loading: boolean) => void;
|
||||
setRepositoryBranches: (repositoryId: string, branches: Branch[]) => void;
|
||||
setRepositoryBranchesLoading: (repositoryId: string, loading: boolean) => void;
|
||||
setRepositoryScripts: (repositoryId: string, scripts: RepositoryScript[]) => void;
|
||||
setRepositoryScriptsLoading: (repositoryId: string, loading: boolean) => void;
|
||||
setSettingsData: (next: Partial<SettingsDataState>) => void;
|
||||
setEditors: (editors: EditorsState['items']) => void;
|
||||
setEditorsLoading: (loading: boolean) => void;
|
||||
@@ -256,6 +260,7 @@ const defaultState = {
|
||||
workspaces: defaultWorkspaceState.workspaces,
|
||||
repositories: defaultWorkspaceState.repositories,
|
||||
repositoryBranches: defaultWorkspaceState.repositoryBranches,
|
||||
repositoryScripts: defaultWorkspaceState.repositoryScripts,
|
||||
executors: defaultSettingsState.executors,
|
||||
environments: defaultSettingsState.environments,
|
||||
settingsAgents: defaultSettingsState.settingsAgents,
|
||||
@@ -306,6 +311,7 @@ function mergeInitialState(initialState?: Partial<AppState>): typeof defaultStat
|
||||
workspaces: { ...defaultState.workspaces, ...initialState.workspaces },
|
||||
repositories: { ...defaultState.repositories, ...initialState.repositories },
|
||||
repositoryBranches: { ...defaultState.repositoryBranches, ...initialState.repositoryBranches },
|
||||
repositoryScripts: { ...defaultState.repositoryScripts, ...initialState.repositoryScripts },
|
||||
executors: { ...defaultState.executors, ...initialState.executors },
|
||||
environments: { ...defaultState.environments, ...initialState.environments },
|
||||
settingsAgents: { ...defaultState.settingsAgents, ...initialState.settingsAgents },
|
||||
@@ -369,6 +375,7 @@ export function createAppStore(initialState?: Partial<AppState>) {
|
||||
workspaces: merged.workspaces,
|
||||
repositories: merged.repositories,
|
||||
repositoryBranches: merged.repositoryBranches,
|
||||
repositoryScripts: merged.repositoryScripts,
|
||||
executors: merged.executors,
|
||||
environments: merged.environments,
|
||||
settingsAgents: merged.settingsAgents,
|
||||
|
||||
@@ -140,6 +140,7 @@ export type Repository = {
|
||||
provider_owner: string;
|
||||
provider_name: string;
|
||||
default_branch: string;
|
||||
scripts?: RepositoryScript[];
|
||||
worktree_branch_prefix: string;
|
||||
pull_before_worktree: boolean;
|
||||
setup_script: string;
|
||||
|
||||
Reference in New Issue
Block a user