formgen/source/logic/ioc/_factory.ts

656 lines
13 KiB
TypeScript
Raw Normal View History

2026-09-30 08:38:52 +02:00
namespace formgen.ioc
2026-04-22 07:47:23 +02:00
{
2026-09-30 08:38:52 +02:00
/**
*/
export type type_description = (
{
type : "checkbox";
label ?: (null | string);
}
|
{
type : "number";
label ?: (null | string);
}
|
{
type : "text";
label ?: (null | string);
}
|
{
type : "color";
label ?: (null | string);
}
|
{
type : "select";
options : Array<
{
value : string;
label : (null | string);
}
>;
label ?: (null | string);
}
|
{
type : "list";
element : type_description;
label ?: (null | string);
}
|
{
type : "group";
members : Record<
string,
{
ioc : type_description;
required ?: boolean;
}
>;
label ?: (null | string);
}
|
{
type : "sum";
items : Array<
{
ioc : type_description;
kind ?: (null | string);
label ?: (null | string);
}
>;
label ?: (null | string);
}
|
{
type : "zerez";
}
);
2026-04-22 07:47:23 +02:00
/**
*/
export function from_raw(
2026-09-30 08:38:52 +02:00
raw : type_description
) : interface_ioc<unknown>
2026-04-22 07:47:23 +02:00
{
switch (raw.type)
{
case "checkbox":
{
return (
2026-09-30 08:38:52 +02:00
new class_ioc_checkbox(
2026-04-22 07:47:23 +02:00
{
2026-09-30 08:38:52 +02:00
"label": (raw.label ?? null),
2026-04-22 07:47:23 +02:00
}
)
);
break;
}
case "number":
{
return (
2026-09-30 08:38:52 +02:00
new class_ioc_number(
2026-04-22 07:47:23 +02:00
{
2026-09-30 08:38:52 +02:00
"label": (raw.label ?? null),
2026-04-22 07:47:23 +02:00
}
)
);
break;
}
case "text":
{
return (
2026-09-30 08:38:52 +02:00
new class_ioc_text(
2026-04-22 07:47:23 +02:00
{
2026-09-30 08:38:52 +02:00
"label": (raw.label ?? null),
2026-04-22 07:47:23 +02:00
}
)
);
break;
}
case "color":
{
return (
2026-09-30 08:38:52 +02:00
new class_ioc_color(
2026-04-22 07:47:23 +02:00
{
2026-09-30 08:38:52 +02:00
"label": (raw.label ?? null),
2026-04-22 07:47:23 +02:00
}
)
);
break;
}
2026-04-22 22:24:32 +02:00
case "select":
{
return (
2026-09-30 08:38:52 +02:00
new class_ioc_select(
2026-04-22 22:24:32 +02:00
(
raw.options
.map(
2026-09-30 08:38:52 +02:00
(option_raw) => ({
"value": option_raw.value,
"label": (option_raw.label ?? String(option_raw.value)),
2026-04-22 22:24:32 +02:00
})
)
),
{
2026-09-30 08:38:52 +02:00
"label": (raw.label ?? null),
2026-04-22 22:24:32 +02:00
}
)
);
}
2026-04-22 07:47:23 +02:00
case "list":
{
return (
2026-09-30 08:38:52 +02:00
new class_ioc_list(
2026-04-22 07:47:23 +02:00
() => from_raw(raw.element),
{
2026-09-30 08:38:52 +02:00
"label": (raw.label ?? null),
2026-04-22 07:47:23 +02:00
}
)
);
break;
}
case "group":
{
return (
2026-09-30 08:38:52 +02:00
new class_ioc_group(
2026-04-22 07:47:23 +02:00
formgen.helpers.list.transform(
formgen.helpers.map.to_pairs(raw.members),
(pair) => ({
"name": pair.key,
2026-09-30 08:38:52 +02:00
"ioc": from_raw(pair.value.ioc),
"marked": (pair.value.required ?? false),
})
),
{
"label": (raw.label ?? null),
}
)
);
break;
}
case "sum":
{
return (
new class_ioc_sum(
formgen.helpers.list.transform(
raw.items,
(raw_item) => ({
"ioc": from_raw(raw_item.ioc),
"kind": raw_item.kind,
"label": raw_item.label,
2026-04-22 07:47:23 +02:00
})
),
{
2026-09-30 08:38:52 +02:00
"label": (raw.label ?? null),
}
)
);
break;
}
case "zerez":
{
return (
new class_ioc_zerez(
/**
* @todo outsource?
*/
async (id) => {
const data_raw : any = await formgen.helpers.zerez.get_unit(id);
return {
"manufacturer": data_raw["certificate"]["certificate_holder"],
"power": data_raw["maximum_active_power_kw"],
};
2026-04-22 07:47:23 +02:00
}
)
);
break;
}
default:
{
2026-09-30 08:38:52 +02:00
throw (new Error("unhandled type " + String(raw)));
2026-04-22 07:47:23 +02:00
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;
}
=
{
}
2026-09-30 08:38:52 +02:00
) : interface_ioc<unknown>
2026-04-22 22:24:32 +02:00
{
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 (
2026-09-30 08:38:52 +02:00
new class_ioc_select<any>(
2026-04-22 22:24:32 +02:00
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 (
2026-09-30 08:38:52 +02:00
new class_ioc_empty(
2026-04-22 22:24:32 +02:00
)
);
break;
}
case "boolean":
{
return (
2026-09-30 08:38:52 +02:00
new class_ioc_checkbox(
2026-04-22 22:24:32 +02:00
{
"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 (
2026-09-30 08:38:52 +02:00
new class_ioc_number(
2026-04-22 22:24:32 +02:00
{
"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 (
2026-09-30 08:38:52 +02:00
new class_ioc_number(
2026-04-22 22:24:32 +02:00
{
"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 (
2026-09-30 08:38:52 +02:00
new class_ioc_date(
2026-04-22 22:24:32 +02:00
{
"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 (
2026-09-30 08:38:52 +02:00
new class_ioc_time(
2026-04-22 22:24:32 +02:00
{
"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 (
2026-09-30 08:38:52 +02:00
new class_ioc_text(
2026-04-22 22:24:32 +02:00
{
"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 (
2026-09-30 08:38:52 +02:00
new class_ioc_text(
2026-04-22 22:24:32 +02:00
{
"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 (
2026-09-30 08:38:52 +02:00
new class_ioc_list(
2026-04-22 22:24:32 +02:00
() => 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":
{
2026-09-30 08:38:52 +02:00
if (
("properties" in schema_adjusted)
&&
! (
("additionalProperties" in schema_adjusted)
&&
(schema_adjusted["additionalProperties"] !== false)
)
)
2026-04-22 22:24:32 +02:00
{
return (
2026-09-30 08:38:52 +02:00
new class_ioc_group(
2026-04-22 22:24:32 +02:00
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,
2026-09-30 08:38:52 +02:00
"ioc": from_json_schema_inner(
2026-04-22 22:24:32 +02:00
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),
}
)
);
}
2026-09-30 08:38:52 +02:00
else if (
! ("properties" in schema_adjusted)
&&
(
("additionalProperties" in schema_adjusted)
&&
(schema_adjusted["additionalProperties"] !== false)
)
)
{
return (
new class_ioc_map<unknown>(
() => from_json_schema_inner(
defs,
root,
(schema_adjusted.additionalProperties as formgen.helpers.json_schema.type_schema),
{
/**
* @todo
*/
"fallback_label": null,
"map_unhandled_refs_to_empty": map_unhandled_refs_to_empty,
}
),
{
"label": (schema_adjusted.title ?? fallback_label ?? null),
}
)
);
}
2026-04-22 22:24:32 +02:00
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 (
2026-09-30 08:38:52 +02:00
new class_ioc_sum(
formgen.helpers.list.transform<int, {ioc : interface_ioc<any>;}>(
2026-04-22 22:24:32 +02:00
formgen.helpers.list.sequence(schema_adjusted.oneOf.length),
(index) => {
const sub_schema : formgen.helpers.json_schema.type_schema = schema_adjusted.oneOf[index];
return {
2026-09-30 08:38:52 +02:00
"ioc": from_json_schema_inner(
2026-04-22 22:24:32 +02:00
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 (
2026-09-30 08:38:52 +02:00
new class_ioc_sum(
formgen.helpers.list.transform<int, {ioc : interface_ioc<any>;}>(
2026-04-22 22:24:32 +02:00
formgen.helpers.list.sequence(schema_adjusted.anyOf.length),
(index) => {
const sub_schema : formgen.helpers.json_schema.type_schema = schema_adjusted.anyOf[index];
return {
2026-09-30 08:38:52 +02:00
"ioc": from_json_schema_inner(
2026-04-22 22:24:32 +02:00
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;
}
=
{
}
2026-09-30 08:38:52 +02:00
) : interface_ioc<unknown>
2026-04-22 22:24:32 +02:00
{
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
}