/* eslint-disable @typescript-eslint/no-unused-vars */ import { ComponentsOverride, AttributesOverride, FlattenedKeyType, FlattenKeys } from '@/client/useHusar.js'; import { buildGraphQLBody, buildMeta, unflattenState } from '@/shared/payload'; import { TailwindPlay } from '@/TailwindPlay/TailwindRenderer.js'; import { ModelTypes } from '@/zeus/index.js'; export function HusarComponents( host?: readonly [string, { readonly headers?: { husar_token: string } | undefined }], ) { type Models = ZEUS extends { ModelEnum: infer R } ? keyof R : never; type Shapes = ZEUS extends { ShapeEnum: infer R } ? keyof R : never; type Views = ZEUS extends { ViewEnum: infer R } ? keyof R : never; // Map nested model type -> flat state map: key is flattened path, value is flattened value type type FlatState = Partial<{ [K in FlattenKeys]: FlattenedKeyType> }>; type SubmitWithPrefix = (data: SData | undefined, prefix: string) => Promise; // Local factory to unify onSubmit handling across View/Model/Shape function makeOnSubmit>({ name, fields, entityType, submit, }: { name: string; fields: ModelTypes['CMSField'][]; entityType: 'view' | 'model' | 'shape'; submit?: (data: SData | undefined) => Promise; }): SubmitWithPrefix { let onSubmit: SubmitWithPrefix; if (!submit) { onSubmit = async (data, prefix) => { if (!host) return; try { const unflattenedData = unflattenState(data as Record); const meta = buildMeta({ entityType, entityName: name, prefix, }); const body = buildGraphQLBody({ name, rootFields: fields, state: (unflattenedData as Record) || {}, meta, }); const extra = host?.[1] || {}; const headers = { 'Content-Type': 'application/json', ...(extra.headers || {}) }; const response = await fetch(host[0], { ...extra, method: 'POST', headers, credentials: 'include', body, }); const result = await response.json(); const ok = !result.errors && !!result.data?.submitResponseState; if (!ok) { console.error('GraphQL submission error:', result.errors || result.data); } } catch (error) { console.error('Submission failed:', error); } }; } else onSubmit = (data) => submit(data); return onSubmit; } function View({ name, data, fields, components, attributes, state, setState, onSubmit: submit, }: { name: T; data?: (T extends string ? (`View${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`View${T}`] : never) : never) | null; fields: ModelTypes['CMSField'][]; components?: ComponentsOverride< T extends string ? (`View${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`View${T}`] : never) : never >; attributes?: AttributesOverride< T extends string ? (`View${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`View${T}`] : never) : never >; state?: FlatState< T extends string ? (`View${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`View${T}`] : never) : never >; setState?: ( state: FlatState< T extends string ? (`View${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`View${T}`] : never) : never >, ) => void; onSubmit?: ( data: | FlatState | undefined, ) => Promise; }) { type ViewModel = T extends string ? `View${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`View${T}`] : never : never; type ViewState = FlatState; const onSubmit = makeOnSubmit({ name: String(name), fields, entityType: 'view', submit }); return ( [0]['components']} fields={fields} modelData={data || undefined} attributes={attributes as Parameters[0]['attributes']} state={state as unknown as Record} setState={setState ? (v) => setState(v as ViewState) : undefined} onSubmit={(v, prefix) => onSubmit(v as ViewState, prefix)} /> ); } function Model({ name, data, fields, components, attributes, state, setState, onSubmit: submit, }: { name: T; data?: (T extends keyof ZEUS_MODELS ? ZEUS_MODELS[T] : never) | null; fields: ModelTypes['CMSField'][]; components?: ComponentsOverride; attributes?: AttributesOverride; state?: FlatState; setState?: (state: FlatState) => void; onSubmit?: (data: FlatState | undefined) => Promise; }) { type ModelModel = T extends keyof ZEUS_MODELS ? ZEUS_MODELS[T] : never; type ModelState = FlatState; const onSubmit = makeOnSubmit({ name: String(name), fields, entityType: 'model', submit }); return ( [0]['components']} fields={fields} modelData={data || undefined} attributes={attributes as Parameters[0]['attributes']} state={state as unknown as Record} setState={setState ? (v) => setState(v as ModelState) : undefined} onSubmit={(v, prefix) => onSubmit(v as ModelState, prefix)} /> ); } function Shape({ name, data, fields, components, attributes, state, setState, onSubmit: submit, }: { name: T; data?: | (T extends string ? (`Shape${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`Shape${T}`] : never) : never) | null; fields: ModelTypes['CMSField'][]; components?: ComponentsOverride< T extends string ? (`Shape${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`Shape${T}`] : never) : never >; attributes?: AttributesOverride< T extends string ? (`Shape${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`Shape${T}`] : never) : never >; state?: FlatState< T extends string ? (`Shape${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`Shape${T}`] : never) : never >; setState?: ( state: FlatState< T extends string ? (`Shape${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`Shape${T}`] : never) : never >, ) => void; onSubmit?: ( data: | FlatState< T extends string ? (`Shape${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`Shape${T}`] : never) : never > | undefined, ) => Promise; }) { type ShapeModel = T extends string ? `Shape${T}` extends keyof ZEUS_MODELS ? ZEUS_MODELS[`Shape${T}`] : never : never; type ShapeState = FlatState; const onSubmit = makeOnSubmit({ name: String(name), fields, entityType: 'shape', submit }); return ( [0]['components']} fields={fields} modelData={data || undefined} attributes={attributes as Parameters[0]['attributes']} state={state as unknown as Record} setState={setState ? (v) => setState(v as ShapeState) : undefined} onSubmit={(v, prefix) => onSubmit(v as ShapeState, prefix)} /> ); } return { View, Model, Shape }; }