formgen/source/logic/input/_factory.ts

511 lines
11 KiB
TypeScript
Raw Normal View History

2026-04-22 07:47:23 +02:00
namespace formgen.input
{
/**
*/
export function from_raw(
raw : any
) : interface_input<unknown>
{
switch (raw.type)
{
case "checkbox":
{
return (
new class_input_checkbox(
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
}
)
);
break;
}
case "number":
{
return (
new class_input_number(
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
}
)
);
break;
}
case "text":
{
return (
new class_input_text(
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
}
)
);
break;
}
case "color":
{
return (
new class_input_color(
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
}
)
);
break;
}
2026-04-22 22:24:32 +02:00
case "select":
{
return (
new class_input_select(
(
raw.options
.map(
(option_raw : Record<string, any>) => ({
"value": option_raw["value"],
"label": (formgen.helpers.map.read<(null | string)>(option_raw, "label", null) ?? String(option_raw["value"])),
})
)
),
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
}
)
);
}
2026-04-22 07:47:23 +02:00
case "list":
{
return (
new class_input_list(
() => from_raw(raw.element),
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
}
)
);
break;
}
case "group":
{
return (
new class_input_group(
formgen.helpers.list.transform(
formgen.helpers.map.to_pairs(raw.members),
(pair) => ({
"name": pair.key,
"input": from_raw(pair.value),
2026-04-22 22:24:32 +02:00
"marked": (pair.value["required"] ?? false),
2026-04-22 07:47:23 +02:00
})
),
{
"label": formgen.helpers.map.read<(null | string)>(raw, "label", null),
}
)
);
break;
}
default:
{
throw (new Error("unhandled type: " + raw.type));
break;
}
}
}
2026-04-22 22:24:32 +02:00
/**
* @todo description
* @todo if-then-else
*/
function from_json_schema_inner(
defs : Map<string, formgen.helpers.json_schema.type_schema>,
root : formgen.helpers.json_schema.type_schema,
json_schema : formgen.helpers.json_schema.type_schema,
{
"fallback_label": fallback_label = null,
"map_unhandled_refs_to_empty": map_unhandled_refs_to_empty = false,
}
:
{
fallback_label ?: (null | string);
map_unhandled_refs_to_empty ?: boolean;
}
=
{
}
) : interface_input<unknown>
{
const schema_adjusted : formgen.helpers.json_schema.type_schema = (() => {
if (! ("$ref" in json_schema))
{
return json_schema;
}
else
{
const cases = [
{
"regexp": new RegExp('^#$'),
"handling": (match) => {
return root;
},
},
{
"regexp": new RegExp('^#/\\$defs/(.*)$'),
"handling": (match) => {
const key : string = match[1];
return defs.get(key);
},
},
];
for (const case_ of cases)
{
const match = json_schema.$ref.match(case_.regexp);
if (match === null)
{
// do nothing
}
else
{
return case_.handling(match);
}
}
if (map_unhandled_refs_to_empty)
{
/**
* @todo warning
*/
return {
"type": "null"
};
}
else
{
throw (new Error("unhandled ref: " + json_schema.$ref));
}
}
}) ();
if ("enum" in schema_adjusted)
{
return (
new class_input_select<any>(
schema_adjusted.enum.map(
(value, index) => (
{
"value": value,
// "label": ("Option " + (index+1).toFixed(0)),
"label": JSON.stringify(value),
}
)
),
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
}
)
);
}
else if ("type" in schema_adjusted)
{
switch (schema_adjusted.type)
{
case "null":
{
return (
new class_input_empty(
)
);
break;
}
case "boolean":
{
return (
new class_input_checkbox(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
2026-04-22 22:53:40 +02:00
"hint": (schema_adjusted.description ?? null),
2026-04-22 22:24:32 +02:00
}
)
);
break;
}
/**
* @todo minimum
* @todo exclusiveMinimum
* @todo maximum
* @todo exclusiveMaximum
* @todo multipleOf
*/
case "integer":
{
return (
new class_input_number(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
2026-04-22 22:53:40 +02:00
"hint": (schema_adjusted.description ?? null),
2026-04-22 22:24:32 +02:00
}
)
);
break;
}
/**
* @todo minimum
* @todo exclusiveMinimum
* @todo maximum
* @todo exclusiveMaximum
* @todo multipleOf
*/
case "number":
{
return (
new class_input_number(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
2026-04-22 22:53:40 +02:00
"hint": (schema_adjusted.description ?? null),
2026-04-22 22:24:32 +02:00
}
)
);
break;
}
/**
* @todo pattern
* @todo minLength
* @todo maxLength
* @todo more format values
*/
case "string":
{
if ("format" in schema_adjusted)
{
switch (schema_adjusted.format)
{
case "date":
{
return (
new class_input_date(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
2026-04-22 22:53:40 +02:00
"hint": (schema_adjusted.description ?? null),
2026-04-22 22:24:32 +02:00
}
)
);
break;
}
case "time":
{
return (
new class_input_time(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
2026-04-22 22:53:40 +02:00
"hint": (schema_adjusted.description ?? null),
2026-04-22 22:24:32 +02:00
}
)
);
break;
}
default:
{
/**
* @todo warning
*/
return (
new class_input_text(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
2026-04-22 22:53:40 +02:00
"hint": (schema_adjusted.description ?? null),
2026-04-22 22:24:32 +02:00
}
)
);
break;
}
}
}
else
{
return (
new class_input_text(
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
2026-04-22 22:53:40 +02:00
"hint": (schema_adjusted.description ?? null),
2026-04-22 22:24:32 +02:00
}
)
);
}
break;
}
case "array":
{
if (! ("items" in schema_adjusted))
{
throw (new Error("can not generate array input without 'items' definition"));
}
else
{
return (
new class_input_list(
() => from_json_schema_inner(
defs,
root,
(schema_adjusted.items as formgen.helpers.json_schema.type_schema),
{
"map_unhandled_refs_to_empty": map_unhandled_refs_to_empty,
}
),
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
}
)
);
}
break;
}
/**
* @todo required
* @todo additionalProperties
* @todo required
*/
case "object":
{
if ("properties" in schema_adjusted)
{
return (
new class_input_group(
formgen.helpers.list.transform(
formgen.helpers.map.to_pairs<
formgen.helpers.json_schema.type_schema
>(schema_adjusted.properties as Record<string, formgen.helpers.json_schema.type_schema>),
(pair : {key : string, value : formgen.helpers.json_schema.type_schema;}) => ({
"name": pair.key,
"input": from_json_schema_inner(
defs,
root,
pair.value,
{
"fallback_label": pair.key,
"map_unhandled_refs_to_empty": map_unhandled_refs_to_empty,
}
),
"marked": (schema_adjusted.required ?? []).includes(pair.key),
})
),
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
}
)
);
}
else
{
throw (new Error("unhandled object situation"));
}
break;
}
default:
{
throw (new Error("unhandled json schema type: " + JSON.stringify(schema_adjusted)));
break;
}
}
}
else if ("not" in schema_adjusted)
{
throw (new Error("not implemented"));
}
else if ("oneOf" in schema_adjusted)
{
return (
new class_input_sum(
formgen.helpers.list.transform<int, {input : interface_input<any>;}>(
formgen.helpers.list.sequence(schema_adjusted.oneOf.length),
(index) => {
const sub_schema : formgen.helpers.json_schema.type_schema = schema_adjusted.oneOf[index];
return {
"input": from_json_schema_inner(
defs,
root,
sub_schema,
{
"map_unhandled_refs_to_empty": map_unhandled_refs_to_empty,
}
),
"label": (sub_schema.title ?? fallback_label ?? ("Art " + (index + 1).toFixed(0))),
};
}
),
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
}
)
);
}
else if ("anyOf" in schema_adjusted)
{
return (
new class_input_sum(
formgen.helpers.list.transform<int, {input : interface_input<any>;}>(
formgen.helpers.list.sequence(schema_adjusted.anyOf.length),
(index) => {
const sub_schema : formgen.helpers.json_schema.type_schema = schema_adjusted.anyOf[index];
return {
"input": from_json_schema_inner(
defs,
root,
sub_schema,
{
"map_unhandled_refs_to_empty": map_unhandled_refs_to_empty,
}
),
"label": (sub_schema.title ?? fallback_label ?? ("Art " + (index + 1).toFixed(0))),
};
}
),
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
}
)
);
}
else if ("allOf" in schema_adjusted)
{
throw (new Error("not implemented"));
}
else
{
throw (new Error("unhandled schema: " + JSON.stringify(schema_adjusted)));
}
}
2026-04-22 07:47:23 +02:00
2026-04-22 22:24:32 +02:00
/**
*/
export function from_json_schema(
root : formgen.helpers.json_schema.type_root,
{
"map_unhandled_refs_to_empty": map_unhandled_refs_to_empty = false,
}
:
{
map_unhandled_refs_to_empty ?: boolean;
}
=
{
}
) : interface_input<unknown>
{
let defs : Map<string, formgen.helpers.json_schema.type_schema> = new Map<string, formgen.helpers.json_schema.type_schema>();
if ("$defs" in root)
{
for (const [name, value] of Object.entries(root.$defs))
{
defs.set(name, value);
}
}
return from_json_schema_inner(
defs,
root,
root,
{
"map_unhandled_refs_to_empty": map_unhandled_refs_to_empty,
}
);
}
2026-04-22 07:47:23 +02:00
}