Add shared frontend domain types
This commit is contained in:
@@ -16,11 +16,11 @@ Goal: migrate the frontend progressively from permissive TypeScript output to ty
|
||||
|
||||
## Phase 1 - Shared Types
|
||||
|
||||
- [ ] Add typed API response contracts for project list, project set, template preview, workflow save, and model tools.
|
||||
- [ ] Add typed runtime state interfaces for persisted state and transient UI callbacks.
|
||||
- [ ] Add typed graph/node/widget interfaces for the subset used by this extension.
|
||||
- [ ] Replace broad object assumptions in `state_manager.ts`.
|
||||
- [ ] Replace broad API payload assumptions in `mjr/api.ts`.
|
||||
- [x] Add typed API response contracts for project list, project set, template preview, workflow save, and model tools.
|
||||
- [x] Add typed runtime state interfaces for persisted state and transient UI callbacks.
|
||||
- [x] Add typed graph/node/widget interfaces for the subset used by this extension.
|
||||
- [x] Replace broad object assumptions in `state_manager.ts`.
|
||||
- [x] Replace broad API payload assumptions in `mjr/api.ts`.
|
||||
|
||||
## Phase 2 - Low-Risk Strict Modules
|
||||
|
||||
|
||||
Vendored
+20
-19
@@ -1,19 +1,20 @@
|
||||
export declare function fetchJSON(url: any, opts: any): Promise<any>;
|
||||
export declare function tryResolveProjectId(folder: any): Promise<any>;
|
||||
export declare function listProjects(): Promise<any>;
|
||||
export declare function setProject(project_name: any, create_base?: boolean): Promise<any>;
|
||||
export declare function getModels(): Promise<any>;
|
||||
export declare function createCustomOut(payload: any): Promise<any>;
|
||||
export declare function previewTemplate(template: any, tokens: any): Promise<any>;
|
||||
export declare function listExistingNames(project_id: any, media?: string): Promise<any>;
|
||||
export declare function saveWorkflow(payload: any): Promise<any>;
|
||||
export declare function scanModelCandidates(missing: any): Promise<any>;
|
||||
export declare function resolveModelRecipes(missing: any): Promise<any>;
|
||||
export declare function saveModelRecipes(items: any): Promise<any>;
|
||||
export declare function downloadModels(items: any): Promise<any>;
|
||||
export declare function getDownloadStatus(job_id: any): Promise<any>;
|
||||
export declare function getFingerprintCacheStatus(): Promise<any>;
|
||||
export declare function buildFingerprintCache(payload: any): Promise<any>;
|
||||
export declare function resolveFingerprint(payload: any): Promise<any>;
|
||||
export declare function searchRegistry(query: any, limit?: number): Promise<any>;
|
||||
export declare function contributeRegistry(payload: any): Promise<any>;
|
||||
import type { ModelToolResponse, ProjectListResponse, ProjectSetResponse, TemplatePreviewResponse, WorkflowSavePayload, WorkflowSaveResponse } from "../types/domain.js";
|
||||
export declare function fetchJSON<T = any>(url: string, opts?: RequestInit): Promise<T>;
|
||||
export declare function tryResolveProjectId(folder: string): Promise<string>;
|
||||
export declare function listProjects(): Promise<ProjectListResponse>;
|
||||
export declare function setProject(project_name: string, create_base?: boolean): Promise<ProjectSetResponse>;
|
||||
export declare function getModels(): Promise<ModelToolResponse>;
|
||||
export declare function createCustomOut(payload: Record<string, unknown>): Promise<TemplatePreviewResponse>;
|
||||
export declare function previewTemplate(template: string, tokens: Record<string, unknown>): Promise<TemplatePreviewResponse>;
|
||||
export declare function listExistingNames(project_id: string, media?: string): Promise<string[]>;
|
||||
export declare function saveWorkflow(payload: WorkflowSavePayload): Promise<WorkflowSaveResponse>;
|
||||
export declare function scanModelCandidates(missing: unknown[]): Promise<ModelToolResponse>;
|
||||
export declare function resolveModelRecipes(missing: unknown[]): Promise<ModelToolResponse>;
|
||||
export declare function saveModelRecipes(items: unknown[]): Promise<ModelToolResponse>;
|
||||
export declare function downloadModels(items: unknown[]): Promise<ModelToolResponse>;
|
||||
export declare function getDownloadStatus(job_id: string): Promise<ModelToolResponse>;
|
||||
export declare function getFingerprintCacheStatus(): Promise<ModelToolResponse>;
|
||||
export declare function buildFingerprintCache(payload: Record<string, unknown>): Promise<ModelToolResponse>;
|
||||
export declare function resolveFingerprint(payload: Record<string, unknown>): Promise<ModelToolResponse>;
|
||||
export declare function searchRegistry(query: string, limit?: number): Promise<ModelToolResponse>;
|
||||
export declare function contributeRegistry(payload: Record<string, unknown>): Promise<ModelToolResponse>;
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+7
-41
@@ -1,41 +1,7 @@
|
||||
export declare const DEFAULT_STATE: {
|
||||
projectName: string;
|
||||
workflowName: string;
|
||||
workflowAsset: string;
|
||||
workflowLastBase: string;
|
||||
workflowNextSuffix: number;
|
||||
workflowPanelOpen: boolean;
|
||||
projectId: string;
|
||||
projectFolder: string;
|
||||
projectExists: any;
|
||||
autoPatch: boolean;
|
||||
autoPatchNewNodes: boolean;
|
||||
autoSwitchTrusted: boolean;
|
||||
autoHookSave: boolean;
|
||||
kind: string;
|
||||
media: string;
|
||||
name: string;
|
||||
modelSelection: string;
|
||||
detectedModelTag: string;
|
||||
useCustomModel: boolean;
|
||||
customModelText: string;
|
||||
modelUpper: boolean;
|
||||
pendingProjectName: string;
|
||||
pendingSelectProjectId: string;
|
||||
lastRelDir: string;
|
||||
lastPrefix: string;
|
||||
pathTemplate: string;
|
||||
showMoreModels: boolean;
|
||||
lastError: string;
|
||||
detected: any;
|
||||
workflowHasSignature: boolean;
|
||||
workflowChecked: boolean;
|
||||
isGraphLoading: boolean;
|
||||
graphLoadToken: number;
|
||||
graphIsEmpty: boolean;
|
||||
};
|
||||
export declare let runtimeState: any;
|
||||
export declare function setRuntimeState(state: any): void;
|
||||
export declare function createRuntimeState(overrides: any): any;
|
||||
export declare function loadState(): any;
|
||||
export declare function saveState(state: any): void;
|
||||
import type { PersistedRuntimeState, RuntimeState } from "./types/domain.js";
|
||||
export declare const DEFAULT_STATE: RuntimeState;
|
||||
export declare let runtimeState: RuntimeState | null;
|
||||
export declare function setRuntimeState(state: RuntimeState | null): void;
|
||||
export declare function createRuntimeState(overrides?: PersistedRuntimeState | Record<string, unknown>): RuntimeState;
|
||||
export declare function loadState(): PersistedRuntimeState | null;
|
||||
export declare function saveState(state: RuntimeState): void;
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"state_manager.js","sourceRoot":"","sources":["../src/state_manager.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"state_manager.js","sourceRoot":"","sources":["../src/state_manager.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,GAAG,4BAA4B,CAAC;AAEjD,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,WAAW,EAAE,EAAE;IACf,YAAY,EAAE,EAAE;IAChB,aAAa,EAAE,EAAE;IACjB,gBAAgB,EAAE,EAAE;IACpB,kBAAkB,EAAE,CAAC;IACrB,iBAAiB,EAAE,KAAK;IACxB,SAAS,EAAE,EAAE;IACb,aAAa,EAAE,EAAE;IACjB,aAAa,EAAE,IAAI;IACnB,SAAS,EAAE,IAAI;IACf,iBAAiB,EAAE,IAAI;IACvB,iBAAiB,EAAE,KAAK;IACxB,YAAY,EAAE,IAAI;IAClB,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,QAAQ;IACf,IAAI,EAAE,EAAE;IACR,cAAc,EAAE,EAAE;IAClB,gBAAgB,EAAE,EAAE;IACpB,cAAc,EAAE,KAAK;IACrB,eAAe,EAAE,EAAE;IACnB,UAAU,EAAE,KAAK;IACjB,kBAAkB,EAAE,EAAE;IACtB,sBAAsB,EAAE,EAAE;IAC1B,UAAU,EAAE,EAAE;IACd,UAAU,EAAE,EAAE;IACd,YAAY,EAAE,sCAAsC;IACpD,cAAc,EAAE,KAAK;IACrB,SAAS,EAAE,EAAE;IACb,QAAQ,EAAE,IAAI;IACd,oBAAoB,EAAE,KAAK;IAC3B,eAAe,EAAE,KAAK;IACtB,cAAc,EAAE,KAAK;IACrB,cAAc,EAAE,CAAC;IACjB,YAAY,EAAE,KAAK;CACpB,CAAC;AAEF,MAAM,CAAC,IAAI,YAAY,GAAwB,IAAI,CAAC;AAEpD,MAAM,UAAU,eAAe,CAAC,KAA0B;IACxD,YAAY,GAAG,KAAK,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,SAA2D;IAC5F,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,aAAa,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAmB;IAC3C,MAAM,IAAI,GAA0B;QAClC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;QACpD,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,cAAc,EAAE,KAAK,CAAC,cAAc;KACrC,CAAC;IACF,IAAI,CAAC;QACH,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,CAAA,CAAC;AAChB,CAAC"}
|
||||
Vendored
+136
@@ -0,0 +1,136 @@
|
||||
export type ProjectMedia = "images" | "videos" | "other" | string;
|
||||
export interface ProjectListEntry {
|
||||
project_id: string;
|
||||
folder?: string;
|
||||
exists?: boolean;
|
||||
archived?: boolean;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
export interface ProjectListResponse {
|
||||
ok?: boolean;
|
||||
projects?: ProjectListEntry[];
|
||||
[key: string]: unknown;
|
||||
}
|
||||
export interface ProjectSetResponse {
|
||||
ok?: boolean;
|
||||
project_id: string;
|
||||
project_folder: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
export interface ProjectResolveResponse {
|
||||
ok?: boolean;
|
||||
project_id?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
export interface TemplatePreviewResponse {
|
||||
ok?: boolean;
|
||||
path?: string;
|
||||
rel_dir?: string;
|
||||
prefix?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
export interface WorkflowSavePayload {
|
||||
project_id: string;
|
||||
workflow_name: string;
|
||||
workflow: unknown;
|
||||
overwrite?: boolean;
|
||||
mirror_to_comfy_workflows?: boolean;
|
||||
use_project_subfolder_in_workflows?: boolean;
|
||||
asset_folder?: string;
|
||||
}
|
||||
export interface WorkflowSaveResponse {
|
||||
ok?: boolean;
|
||||
file?: string;
|
||||
project_rel_path?: string;
|
||||
workflow_rel_dir?: string;
|
||||
comfy_workflow_rel?: string;
|
||||
mirrored?: boolean;
|
||||
mirror_error?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
export interface ModelToolResponse {
|
||||
ok?: boolean;
|
||||
items?: unknown[];
|
||||
missing?: unknown[];
|
||||
results?: unknown[];
|
||||
entries?: unknown[];
|
||||
candidates?: unknown[];
|
||||
recipes?: unknown[];
|
||||
job_id?: string;
|
||||
status?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
export interface DetectedProject {
|
||||
mode: "none" | "signature" | "path" | string;
|
||||
project_folder: string;
|
||||
project_id: string;
|
||||
confidence: number;
|
||||
}
|
||||
export interface RuntimeUiCallbacks {
|
||||
updateStatus?: () => void | Promise<void>;
|
||||
updateResolve?: () => void | Promise<void>;
|
||||
updateWorkflowBlock?: () => void | Promise<void>;
|
||||
updateTargetLabel?: () => void | Promise<void>;
|
||||
refreshExistingNames?: () => void | Promise<void>;
|
||||
refreshMissingStatus?: () => void | Promise<void>;
|
||||
updatePreview?: () => void | Promise<void>;
|
||||
resetForProjectChange?: () => void;
|
||||
refreshProjectsList?: (force?: boolean) => void | Promise<void>;
|
||||
buildWorkflowName?: () => string;
|
||||
setWorkflowName?: (name: string) => void;
|
||||
}
|
||||
export interface RuntimeState {
|
||||
projectName: string;
|
||||
workflowName: string;
|
||||
workflowAsset: string;
|
||||
workflowLastBase: string;
|
||||
workflowNextSuffix: number;
|
||||
workflowPanelOpen: boolean;
|
||||
projectId: string;
|
||||
projectFolder: string;
|
||||
projectExists: boolean | null;
|
||||
autoPatch: boolean;
|
||||
autoPatchNewNodes: boolean;
|
||||
autoSwitchTrusted: boolean;
|
||||
autoHookSave: boolean;
|
||||
kind: string;
|
||||
media: ProjectMedia;
|
||||
name: string;
|
||||
modelSelection: string;
|
||||
detectedModelTag: string;
|
||||
useCustomModel: boolean;
|
||||
customModelText: string;
|
||||
modelUpper: boolean;
|
||||
pendingProjectName: string;
|
||||
pendingSelectProjectId: string;
|
||||
lastRelDir: string;
|
||||
lastPrefix: string;
|
||||
pathTemplate: string;
|
||||
showMoreModels: boolean;
|
||||
lastError: string;
|
||||
detected: DetectedProject | null;
|
||||
workflowHasSignature: boolean;
|
||||
workflowChecked: boolean;
|
||||
isGraphLoading: boolean;
|
||||
graphLoadToken: number;
|
||||
graphIsEmpty: boolean;
|
||||
customModel?: string;
|
||||
_ui?: RuntimeUiCallbacks;
|
||||
_emptyGraphPromptToken?: number | null;
|
||||
}
|
||||
export type PersistedRuntimeState = Partial<Pick<RuntimeState, "projectName" | "workflowName" | "workflowAsset" | "workflowLastBase" | "workflowNextSuffix" | "workflowPanelOpen" | "projectId" | "projectFolder" | "autoPatch" | "autoPatchNewNodes" | "autoSwitchTrusted" | "autoHookSave" | "kind" | "media" | "name" | "modelSelection" | "detectedModelTag" | "useCustomModel" | "customModelText" | "modelUpper" | "pendingProjectName" | "pendingSelectProjectId" | "lastRelDir" | "lastPrefix" | "pathTemplate" | "showMoreModels">>;
|
||||
export interface ComfyWidget {
|
||||
name?: string;
|
||||
value?: unknown;
|
||||
options?: {
|
||||
values?: unknown[];
|
||||
[key: string]: unknown;
|
||||
};
|
||||
[key: string]: unknown;
|
||||
}
|
||||
export interface ComfyNode {
|
||||
type?: string;
|
||||
title?: string;
|
||||
widgets?: ComfyWidget[];
|
||||
[key: string]: unknown;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=domain.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"domain.js","sourceRoot":"","sources":["../../src/types/domain.ts"],"names":[],"mappings":""}
|
||||
+47
-37
@@ -1,3 +1,13 @@
|
||||
import type {
|
||||
ModelToolResponse,
|
||||
ProjectListResponse,
|
||||
ProjectResolveResponse,
|
||||
ProjectSetResponse,
|
||||
TemplatePreviewResponse,
|
||||
WorkflowSavePayload,
|
||||
WorkflowSaveResponse,
|
||||
} from "../types/domain.js";
|
||||
|
||||
let _csrfTokenPromise = null;
|
||||
|
||||
function _getApiKey() {
|
||||
@@ -41,7 +51,7 @@ async function _getCsrfToken(forceRefresh = false) {
|
||||
return _csrfTokenPromise;
|
||||
}
|
||||
|
||||
export async function fetchJSON(url, opts) {
|
||||
export async function fetchJSON<T = any>(url: string, opts?: RequestInit): Promise<T> {
|
||||
const o = opts ? { ...opts } : {};
|
||||
o.credentials = o.credentials || "same-origin";
|
||||
o.headers = { ...(o.headers || {}) };
|
||||
@@ -85,130 +95,130 @@ export async function fetchJSON(url, opts) {
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function tryResolveProjectId(folder) {
|
||||
export async function tryResolveProjectId(folder: string): Promise<string> {
|
||||
try {
|
||||
const data = await fetchJSON(`/mjr_project/resolve?folder=${encodeURIComponent(folder)}`);
|
||||
const data = await fetchJSON<ProjectResolveResponse>(`/mjr_project/resolve?folder=${encodeURIComponent(folder)}`);
|
||||
if (data?.ok) return data.project_id || "";
|
||||
} catch (_) {}
|
||||
return "";
|
||||
}
|
||||
|
||||
export async function listProjects() {
|
||||
return fetchJSON("/mjr_project/list");
|
||||
export async function listProjects(): Promise<ProjectListResponse> {
|
||||
return fetchJSON<ProjectListResponse>("/mjr_project/list");
|
||||
}
|
||||
|
||||
export async function setProject(project_name, create_base = true) {
|
||||
return fetchJSON("/mjr_project/set", {
|
||||
export async function setProject(project_name: string, create_base = true): Promise<ProjectSetResponse> {
|
||||
return fetchJSON<ProjectSetResponse>("/mjr_project/set", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ project_name, create_base }),
|
||||
});
|
||||
}
|
||||
|
||||
export async function getModels() {
|
||||
return fetchJSON("/mjr_project/models");
|
||||
export async function getModels(): Promise<ModelToolResponse> {
|
||||
return fetchJSON<ModelToolResponse>("/mjr_project/models");
|
||||
}
|
||||
|
||||
export async function createCustomOut(payload) {
|
||||
return fetchJSON("/mjr_project/create_custom_out", {
|
||||
export async function createCustomOut(payload: Record<string, unknown>): Promise<TemplatePreviewResponse> {
|
||||
return fetchJSON<TemplatePreviewResponse>("/mjr_project/create_custom_out", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload || {}),
|
||||
});
|
||||
}
|
||||
|
||||
export async function previewTemplate(template, tokens) {
|
||||
return fetchJSON("/mjr_project/preview_template", {
|
||||
export async function previewTemplate(template: string, tokens: Record<string, unknown>): Promise<TemplatePreviewResponse> {
|
||||
return fetchJSON<TemplatePreviewResponse>("/mjr_project/preview_template", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ template, tokens: tokens || {} }),
|
||||
});
|
||||
}
|
||||
|
||||
export async function listExistingNames(project_id, media = "images") {
|
||||
export async function listExistingNames(project_id: string, media = "images"): Promise<string[]> {
|
||||
const qs = new URLSearchParams({
|
||||
project_id: project_id || "",
|
||||
media: media || "images",
|
||||
});
|
||||
const data = await fetchJSON(`/mjr_project/assets/list_names?${qs.toString()}`);
|
||||
const data = await fetchJSON<{ names?: unknown[] }>(`/mjr_project/assets/list_names?${qs.toString()}`);
|
||||
return Array.isArray(data?.names) ? data.names : [];
|
||||
}
|
||||
|
||||
export async function saveWorkflow(payload) {
|
||||
return fetchJSON("/mjr_project/workflow/save", {
|
||||
export async function saveWorkflow(payload: WorkflowSavePayload): Promise<WorkflowSaveResponse> {
|
||||
return fetchJSON<WorkflowSaveResponse>("/mjr_project/workflow/save", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload || {}),
|
||||
});
|
||||
}
|
||||
|
||||
export async function scanModelCandidates(missing) {
|
||||
return fetchJSON("/mjr_models/scan_candidates", {
|
||||
export async function scanModelCandidates(missing: unknown[]): Promise<ModelToolResponse> {
|
||||
return fetchJSON<ModelToolResponse>("/mjr_models/scan_candidates", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ missing: missing || [] }),
|
||||
});
|
||||
}
|
||||
|
||||
export async function resolveModelRecipes(missing) {
|
||||
return fetchJSON("/mjr_models/resolve_recipes", {
|
||||
export async function resolveModelRecipes(missing: unknown[]): Promise<ModelToolResponse> {
|
||||
return fetchJSON<ModelToolResponse>("/mjr_models/resolve_recipes", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ missing: missing || [] }),
|
||||
});
|
||||
}
|
||||
|
||||
export async function saveModelRecipes(items) {
|
||||
return fetchJSON("/mjr_models/save_recipes", {
|
||||
export async function saveModelRecipes(items: unknown[]): Promise<ModelToolResponse> {
|
||||
return fetchJSON<ModelToolResponse>("/mjr_models/save_recipes", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ items: items || [] }),
|
||||
});
|
||||
}
|
||||
|
||||
export async function downloadModels(items) {
|
||||
return fetchJSON("/mjr_models/download", {
|
||||
export async function downloadModels(items: unknown[]): Promise<ModelToolResponse> {
|
||||
return fetchJSON<ModelToolResponse>("/mjr_models/download", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ items: items || [] }),
|
||||
});
|
||||
}
|
||||
|
||||
export async function getDownloadStatus(job_id) {
|
||||
export async function getDownloadStatus(job_id: string): Promise<ModelToolResponse> {
|
||||
const qs = new URLSearchParams({ job_id: job_id || "" });
|
||||
return fetchJSON(`/mjr_models/download_status?${qs.toString()}`);
|
||||
return fetchJSON<ModelToolResponse>(`/mjr_models/download_status?${qs.toString()}`);
|
||||
}
|
||||
|
||||
export async function getFingerprintCacheStatus() {
|
||||
return fetchJSON("/mjr_models/fingerprint_cache_status");
|
||||
export async function getFingerprintCacheStatus(): Promise<ModelToolResponse> {
|
||||
return fetchJSON<ModelToolResponse>("/mjr_models/fingerprint_cache_status");
|
||||
}
|
||||
|
||||
export async function buildFingerprintCache(payload) {
|
||||
return fetchJSON("/mjr_models/build_fingerprint_cache", {
|
||||
export async function buildFingerprintCache(payload: Record<string, unknown>): Promise<ModelToolResponse> {
|
||||
return fetchJSON<ModelToolResponse>("/mjr_models/build_fingerprint_cache", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload || {}),
|
||||
});
|
||||
}
|
||||
|
||||
export async function resolveFingerprint(payload) {
|
||||
return fetchJSON("/mjr_models/resolve_by_fingerprint", {
|
||||
export async function resolveFingerprint(payload: Record<string, unknown>): Promise<ModelToolResponse> {
|
||||
return fetchJSON<ModelToolResponse>("/mjr_models/resolve_by_fingerprint", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload || {}),
|
||||
});
|
||||
}
|
||||
|
||||
export async function searchRegistry(query, limit = 6) {
|
||||
return fetchJSON("/mjr_models/registry/search", {
|
||||
export async function searchRegistry(query: string, limit = 6): Promise<ModelToolResponse> {
|
||||
return fetchJSON<ModelToolResponse>("/mjr_models/registry/search", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ query: String(query || ""), limit }),
|
||||
});
|
||||
}
|
||||
|
||||
export async function contributeRegistry(payload) {
|
||||
return fetchJSON("/mjr_models/registry/contribute", {
|
||||
export async function contributeRegistry(payload: Record<string, unknown>): Promise<ModelToolResponse> {
|
||||
return fetchJSON<ModelToolResponse>("/mjr_models/registry/contribute", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload || {}),
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { PersistedRuntimeState, RuntimeState } from "./types/domain.js";
|
||||
|
||||
const STORAGE_KEY = "mjr_project_settings_state";
|
||||
|
||||
export const DEFAULT_STATE = {
|
||||
export const DEFAULT_STATE: RuntimeState = {
|
||||
projectName: "",
|
||||
workflowName: "",
|
||||
workflowAsset: "",
|
||||
@@ -37,17 +39,17 @@ export const DEFAULT_STATE = {
|
||||
graphIsEmpty: false,
|
||||
};
|
||||
|
||||
export let runtimeState = null;
|
||||
export let runtimeState: RuntimeState | null = null;
|
||||
|
||||
export function setRuntimeState(state) {
|
||||
export function setRuntimeState(state: RuntimeState | null) {
|
||||
runtimeState = state;
|
||||
}
|
||||
|
||||
export function createRuntimeState(overrides) {
|
||||
export function createRuntimeState(overrides?: PersistedRuntimeState | Record<string, unknown>): RuntimeState {
|
||||
return Object.assign({}, DEFAULT_STATE, overrides || {});
|
||||
}
|
||||
|
||||
export function loadState() {
|
||||
export function loadState(): PersistedRuntimeState | null {
|
||||
try {
|
||||
const raw = localStorage.getItem(STORAGE_KEY);
|
||||
if (!raw) return null;
|
||||
@@ -57,8 +59,8 @@ export function loadState() {
|
||||
}
|
||||
}
|
||||
|
||||
export function saveState(state) {
|
||||
const data = {
|
||||
export function saveState(state: RuntimeState) {
|
||||
const data: PersistedRuntimeState = {
|
||||
projectName: state.projectName,
|
||||
workflowName: state.workflowName,
|
||||
workflowAsset: state.workflowAsset,
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
export type ProjectMedia = "images" | "videos" | "other" | string;
|
||||
|
||||
export interface ProjectListEntry {
|
||||
project_id: string;
|
||||
folder?: string;
|
||||
exists?: boolean;
|
||||
archived?: boolean;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface ProjectListResponse {
|
||||
ok?: boolean;
|
||||
projects?: ProjectListEntry[];
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface ProjectSetResponse {
|
||||
ok?: boolean;
|
||||
project_id: string;
|
||||
project_folder: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface ProjectResolveResponse {
|
||||
ok?: boolean;
|
||||
project_id?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface TemplatePreviewResponse {
|
||||
ok?: boolean;
|
||||
path?: string;
|
||||
rel_dir?: string;
|
||||
prefix?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface WorkflowSavePayload {
|
||||
project_id: string;
|
||||
workflow_name: string;
|
||||
workflow: unknown;
|
||||
overwrite?: boolean;
|
||||
mirror_to_comfy_workflows?: boolean;
|
||||
use_project_subfolder_in_workflows?: boolean;
|
||||
asset_folder?: string;
|
||||
}
|
||||
|
||||
export interface WorkflowSaveResponse {
|
||||
ok?: boolean;
|
||||
file?: string;
|
||||
project_rel_path?: string;
|
||||
workflow_rel_dir?: string;
|
||||
comfy_workflow_rel?: string;
|
||||
mirrored?: boolean;
|
||||
mirror_error?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface ModelToolResponse {
|
||||
ok?: boolean;
|
||||
items?: unknown[];
|
||||
missing?: unknown[];
|
||||
results?: unknown[];
|
||||
entries?: unknown[];
|
||||
candidates?: unknown[];
|
||||
recipes?: unknown[];
|
||||
job_id?: string;
|
||||
status?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface DetectedProject {
|
||||
mode: "none" | "signature" | "path" | string;
|
||||
project_folder: string;
|
||||
project_id: string;
|
||||
confidence: number;
|
||||
}
|
||||
|
||||
export interface RuntimeUiCallbacks {
|
||||
updateStatus?: () => void | Promise<void>;
|
||||
updateResolve?: () => void | Promise<void>;
|
||||
updateWorkflowBlock?: () => void | Promise<void>;
|
||||
updateTargetLabel?: () => void | Promise<void>;
|
||||
refreshExistingNames?: () => void | Promise<void>;
|
||||
refreshMissingStatus?: () => void | Promise<void>;
|
||||
updatePreview?: () => void | Promise<void>;
|
||||
resetForProjectChange?: () => void;
|
||||
refreshProjectsList?: (force?: boolean) => void | Promise<void>;
|
||||
buildWorkflowName?: () => string;
|
||||
setWorkflowName?: (name: string) => void;
|
||||
}
|
||||
|
||||
export interface RuntimeState {
|
||||
projectName: string;
|
||||
workflowName: string;
|
||||
workflowAsset: string;
|
||||
workflowLastBase: string;
|
||||
workflowNextSuffix: number;
|
||||
workflowPanelOpen: boolean;
|
||||
projectId: string;
|
||||
projectFolder: string;
|
||||
projectExists: boolean | null;
|
||||
autoPatch: boolean;
|
||||
autoPatchNewNodes: boolean;
|
||||
autoSwitchTrusted: boolean;
|
||||
autoHookSave: boolean;
|
||||
kind: string;
|
||||
media: ProjectMedia;
|
||||
name: string;
|
||||
modelSelection: string;
|
||||
detectedModelTag: string;
|
||||
useCustomModel: boolean;
|
||||
customModelText: string;
|
||||
modelUpper: boolean;
|
||||
pendingProjectName: string;
|
||||
pendingSelectProjectId: string;
|
||||
lastRelDir: string;
|
||||
lastPrefix: string;
|
||||
pathTemplate: string;
|
||||
showMoreModels: boolean;
|
||||
lastError: string;
|
||||
detected: DetectedProject | null;
|
||||
workflowHasSignature: boolean;
|
||||
workflowChecked: boolean;
|
||||
isGraphLoading: boolean;
|
||||
graphLoadToken: number;
|
||||
graphIsEmpty: boolean;
|
||||
customModel?: string;
|
||||
_ui?: RuntimeUiCallbacks;
|
||||
_emptyGraphPromptToken?: number | null;
|
||||
}
|
||||
|
||||
export type PersistedRuntimeState = Partial<
|
||||
Pick<
|
||||
RuntimeState,
|
||||
| "projectName"
|
||||
| "workflowName"
|
||||
| "workflowAsset"
|
||||
| "workflowLastBase"
|
||||
| "workflowNextSuffix"
|
||||
| "workflowPanelOpen"
|
||||
| "projectId"
|
||||
| "projectFolder"
|
||||
| "autoPatch"
|
||||
| "autoPatchNewNodes"
|
||||
| "autoSwitchTrusted"
|
||||
| "autoHookSave"
|
||||
| "kind"
|
||||
| "media"
|
||||
| "name"
|
||||
| "modelSelection"
|
||||
| "detectedModelTag"
|
||||
| "useCustomModel"
|
||||
| "customModelText"
|
||||
| "modelUpper"
|
||||
| "pendingProjectName"
|
||||
| "pendingSelectProjectId"
|
||||
| "lastRelDir"
|
||||
| "lastPrefix"
|
||||
| "pathTemplate"
|
||||
| "showMoreModels"
|
||||
>
|
||||
>;
|
||||
|
||||
export interface ComfyWidget {
|
||||
name?: string;
|
||||
value?: unknown;
|
||||
options?: {
|
||||
values?: unknown[];
|
||||
[key: string]: unknown;
|
||||
};
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface ComfyNode {
|
||||
type?: string;
|
||||
title?: string;
|
||||
widgets?: ComfyWidget[];
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user