91 lines
2.1 KiB
TypeScript
91 lines
2.1 KiB
TypeScript
import { create, createStore, useStore } from "zustand";
|
|
import type { Template } from "./types";
|
|
import { createContext, useContext } from "react";
|
|
import { buildTemplate } from "./api";
|
|
|
|
interface TemplateEditorState {
|
|
template: Template;
|
|
currentFilePath: string;
|
|
isBuildInProgress: boolean;
|
|
isBuildOutputVisible: boolean;
|
|
buildOutput: string;
|
|
|
|
startBuild: ({ imageTag }: { imageTag: string }) => Promise<void>;
|
|
|
|
setCurrentFilePath: (path: string) => void;
|
|
|
|
addBuildOutputChunk: (chunk: string) => void;
|
|
|
|
toggleBuildOutput: () => void;
|
|
}
|
|
|
|
type TemplateEditorStore = ReturnType<typeof createTemplateEditorStore>;
|
|
|
|
function createTemplateEditorStore({
|
|
template,
|
|
currentFilePath,
|
|
}: { template: Template; currentFilePath: string }) {
|
|
return createStore<TemplateEditorState>()((set, get) => ({
|
|
template,
|
|
currentFilePath,
|
|
isBuildInProgress: false,
|
|
isBuildOutputVisible: false,
|
|
buildOutput: "",
|
|
|
|
startBuild: async ({ imageTag }) => {
|
|
const state = get();
|
|
|
|
set({
|
|
isBuildInProgress: true,
|
|
isBuildOutputVisible: true,
|
|
buildOutput: "",
|
|
});
|
|
|
|
try {
|
|
await buildTemplate({
|
|
imageTag,
|
|
templateName: state.template.name,
|
|
onBuildOutput: state.addBuildOutputChunk,
|
|
});
|
|
} catch {
|
|
// TODO: handle build error
|
|
} finally {
|
|
set({ isBuildInProgress: false });
|
|
}
|
|
},
|
|
|
|
setCurrentFilePath: (path) => set({ currentFilePath: path }),
|
|
|
|
addBuildOutputChunk: (chunk) =>
|
|
set((state) => ({
|
|
...state,
|
|
buildOutput: state.buildOutput + chunk,
|
|
})),
|
|
|
|
toggleBuildOutput: () =>
|
|
set((state) => ({
|
|
...state,
|
|
isBuildOutputVisible: !state.isBuildOutputVisible,
|
|
})),
|
|
}));
|
|
}
|
|
|
|
const TemplateEditorStoreContext = createContext<TemplateEditorStore | null>(
|
|
null,
|
|
);
|
|
|
|
function useTemplateEditorStore<T>(
|
|
selector: (state: TemplateEditorState) => T,
|
|
): T {
|
|
const store = useContext(TemplateEditorStoreContext);
|
|
if (!store) throw new Error("TemplateEditorStore not in context");
|
|
return useStore(store, selector);
|
|
}
|
|
|
|
export {
|
|
TemplateEditorStoreContext,
|
|
createTemplateEditorStore,
|
|
useTemplateEditorStore,
|
|
};
|
|
export type { TemplateEditorStore, TemplateEditorState };
|