2023-01-18 06:01:32 +00:00
|
|
|
import { doesExist, Maybe } from '@apextoaster/js-utils';
|
2023-01-18 13:20:12 +00:00
|
|
|
import { merge } from 'lodash';
|
2023-01-17 02:11:10 +00:00
|
|
|
import { Img2ImgParams, InpaintParams, ModelParams, OutpaintParams, STATUS_SUCCESS, Txt2ImgParams, UpscaleParams } from './client.js';
|
2023-01-06 16:52:42 +00:00
|
|
|
|
2023-01-10 04:59:08 +00:00
|
|
|
export interface ConfigNumber {
|
2023-01-08 20:25:25 +00:00
|
|
|
default: number;
|
|
|
|
min: number;
|
|
|
|
max: number;
|
|
|
|
step: number;
|
|
|
|
}
|
|
|
|
|
2023-01-10 04:59:08 +00:00
|
|
|
export interface ConfigString {
|
|
|
|
default: string;
|
2023-03-02 23:24:45 +00:00
|
|
|
keys: Record<string, string>;
|
2023-01-10 04:59:08 +00:00
|
|
|
}
|
|
|
|
|
2023-01-27 23:27:11 +00:00
|
|
|
/**
|
|
|
|
* Helper type to filter keys whose value extends `TValid`.
|
|
|
|
*/
|
2023-01-13 20:39:07 +00:00
|
|
|
export type KeyFilter<T extends object, TValid = number | string> = {
|
|
|
|
[K in keyof T]: T[K] extends TValid ? K : never;
|
2023-01-08 20:25:25 +00:00
|
|
|
}[keyof T];
|
|
|
|
|
2023-01-27 23:27:11 +00:00
|
|
|
/**
|
|
|
|
* Keep fields with a file-like value, but make them optional.
|
|
|
|
*/
|
2023-01-13 20:39:07 +00:00
|
|
|
export type ConfigFiles<T extends object> = {
|
2023-02-12 22:52:50 +00:00
|
|
|
[K in KeyFilter<T, Blob | File | Array<Blob | File>>]: Maybe<T[K]>;
|
2023-01-13 20:39:07 +00:00
|
|
|
};
|
|
|
|
|
2023-01-27 23:27:11 +00:00
|
|
|
/**
|
|
|
|
* Map numbers and strings to their corresponding config types and drop the rest of the fields.
|
|
|
|
*/
|
2023-01-08 20:25:25 +00:00
|
|
|
export type ConfigRanges<T extends object> = {
|
2023-01-10 04:59:08 +00:00
|
|
|
[K in KeyFilter<T>]: T[K] extends number ? ConfigNumber : T[K] extends string ? ConfigString : never;
|
2023-01-08 20:25:25 +00:00
|
|
|
};
|
|
|
|
|
2023-01-27 23:27:11 +00:00
|
|
|
/**
|
|
|
|
* Keep fields whose value extends `TValid` and drop the rest.
|
|
|
|
*/
|
2023-01-13 20:39:07 +00:00
|
|
|
export type ConfigState<T extends object, TValid = number | string> = {
|
|
|
|
[K in KeyFilter<T, TValid>]: T[K] extends TValid ? T[K] : never;
|
2023-01-11 02:43:14 +00:00
|
|
|
};
|
|
|
|
|
2023-01-27 23:27:11 +00:00
|
|
|
// eslint does not understand how to indent this and expects each line to increase
|
2023-01-17 02:11:10 +00:00
|
|
|
/* eslint-disable */
|
2023-01-27 23:27:11 +00:00
|
|
|
/**
|
|
|
|
* Combine all of the request parameter groups, make optional parameters required, then
|
|
|
|
* map them to the number/string ranges.
|
|
|
|
*/
|
2023-01-18 13:20:12 +00:00
|
|
|
export type ServerParams = ConfigRanges<Required<
|
2023-01-17 02:11:10 +00:00
|
|
|
Img2ImgParams &
|
|
|
|
Txt2ImgParams &
|
|
|
|
InpaintParams &
|
|
|
|
ModelParams &
|
|
|
|
OutpaintParams &
|
|
|
|
UpscaleParams
|
2023-01-18 05:04:57 +00:00
|
|
|
>> & {
|
|
|
|
version: string;
|
|
|
|
};
|
2023-01-17 02:11:10 +00:00
|
|
|
/* eslint-enable */
|
2023-01-10 04:59:08 +00:00
|
|
|
|
2023-01-27 23:27:11 +00:00
|
|
|
/**
|
|
|
|
* Parameters that can be customized on the client, through the config file or settings tab.
|
|
|
|
*/
|
2023-01-18 13:20:12 +00:00
|
|
|
export interface ClientParams {
|
|
|
|
model: ConfigString;
|
|
|
|
platform: ConfigString;
|
|
|
|
scheduler: ConfigString;
|
|
|
|
prompt: ConfigString;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface Config<T = ClientParams> {
|
2023-01-10 04:59:08 +00:00
|
|
|
api: {
|
|
|
|
root: string;
|
|
|
|
};
|
2023-01-18 13:20:12 +00:00
|
|
|
params: T;
|
2023-01-10 04:59:08 +00:00
|
|
|
}
|
|
|
|
|
2023-01-09 04:15:58 +00:00
|
|
|
export const IMAGE_FILTER = '.bmp, .jpg, .jpeg, .png';
|
2023-01-18 05:04:57 +00:00
|
|
|
export const PARAM_VERSION = '>=0.4.0';
|
|
|
|
|
2023-01-13 03:12:20 +00:00
|
|
|
export const STALE_TIME = 300_000; // 5 minutes
|
|
|
|
export const POLL_TIME = 5_000; // 5 seconds
|
2023-01-13 20:39:07 +00:00
|
|
|
export const SAVE_TIME = 5_000; // 5 seconds
|
2023-01-10 04:59:08 +00:00
|
|
|
|
|
|
|
export async function loadConfig(): Promise<Config> {
|
2023-01-14 00:29:14 +00:00
|
|
|
const configPath = new URL('./config.json', window.location.href);
|
2023-01-10 04:59:08 +00:00
|
|
|
const configReq = await fetch(configPath);
|
|
|
|
if (configReq.status === STATUS_SUCCESS) {
|
|
|
|
return configReq.json();
|
|
|
|
} else {
|
|
|
|
throw new Error('could not load config');
|
|
|
|
}
|
|
|
|
}
|
2023-01-18 06:01:32 +00:00
|
|
|
|
2023-01-18 13:20:12 +00:00
|
|
|
export function mergeConfig(client: Config, server: ServerParams): Config<ServerParams> {
|
|
|
|
const full = merge({}, server, client.params);;
|
|
|
|
|
|
|
|
return {
|
|
|
|
...client,
|
|
|
|
params: full,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-01-18 06:01:32 +00:00
|
|
|
export function getApiRoot(config: Config): string {
|
|
|
|
const query = new URLSearchParams(window.location.search);
|
|
|
|
const api = query.get('api');
|
|
|
|
|
|
|
|
if (doesExist(api)) {
|
|
|
|
return api;
|
|
|
|
} else {
|
|
|
|
return config.api.root;
|
|
|
|
}
|
|
|
|
}
|