656 lines
13 KiB
TypeScript
656 lines
13 KiB
TypeScript
namespace formgen.ioc
|
|
{
|
|
|
|
/**
|
|
*/
|
|
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";
|
|
}
|
|
);
|
|
|
|
|
|
/**
|
|
*/
|
|
export function from_raw(
|
|
raw : type_description
|
|
) : interface_ioc<unknown>
|
|
{
|
|
switch (raw.type)
|
|
{
|
|
case "checkbox":
|
|
{
|
|
return (
|
|
new class_ioc_checkbox(
|
|
{
|
|
"label": (raw.label ?? null),
|
|
}
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
case "number":
|
|
{
|
|
return (
|
|
new class_ioc_number(
|
|
{
|
|
"label": (raw.label ?? null),
|
|
}
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
case "text":
|
|
{
|
|
return (
|
|
new class_ioc_text(
|
|
{
|
|
"label": (raw.label ?? null),
|
|
}
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
case "color":
|
|
{
|
|
return (
|
|
new class_ioc_color(
|
|
{
|
|
"label": (raw.label ?? null),
|
|
}
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
case "select":
|
|
{
|
|
return (
|
|
new class_ioc_select(
|
|
(
|
|
raw.options
|
|
.map(
|
|
(option_raw) => ({
|
|
"value": option_raw.value,
|
|
"label": (option_raw.label ?? String(option_raw.value)),
|
|
})
|
|
)
|
|
),
|
|
{
|
|
"label": (raw.label ?? null),
|
|
}
|
|
)
|
|
);
|
|
}
|
|
case "list":
|
|
{
|
|
return (
|
|
new class_ioc_list(
|
|
() => from_raw(raw.element),
|
|
{
|
|
"label": (raw.label ?? null),
|
|
}
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
case "group":
|
|
{
|
|
return (
|
|
new class_ioc_group(
|
|
formgen.helpers.list.transform(
|
|
formgen.helpers.map.to_pairs(raw.members),
|
|
(pair) => ({
|
|
"name": pair.key,
|
|
"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,
|
|
})
|
|
),
|
|
{
|
|
"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"],
|
|
};
|
|
}
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
throw (new Error("unhandled type " + String(raw)));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @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_ioc<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_ioc_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_ioc_empty(
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
case "boolean":
|
|
{
|
|
return (
|
|
new class_ioc_checkbox(
|
|
{
|
|
"label": (schema_adjusted.title ?? fallback_label ?? null),
|
|
"hint": (schema_adjusted.description ?? null),
|
|
}
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
/**
|
|
* @todo minimum
|
|
* @todo exclusiveMinimum
|
|
* @todo maximum
|
|
* @todo exclusiveMaximum
|
|
* @todo multipleOf
|
|
*/
|
|
case "integer":
|
|
{
|
|
return (
|
|
new class_ioc_number(
|
|
{
|
|
"label": (schema_adjusted.title ?? fallback_label ?? null),
|
|
"hint": (schema_adjusted.description ?? null),
|
|
}
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
/**
|
|
* @todo minimum
|
|
* @todo exclusiveMinimum
|
|
* @todo maximum
|
|
* @todo exclusiveMaximum
|
|
* @todo multipleOf
|
|
*/
|
|
case "number":
|
|
{
|
|
return (
|
|
new class_ioc_number(
|
|
{
|
|
"label": (schema_adjusted.title ?? fallback_label ?? null),
|
|
"hint": (schema_adjusted.description ?? null),
|
|
}
|
|
)
|
|
);
|
|
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_ioc_date(
|
|
{
|
|
"label": (schema_adjusted.title ?? fallback_label ?? null),
|
|
"hint": (schema_adjusted.description ?? null),
|
|
}
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
case "time":
|
|
{
|
|
return (
|
|
new class_ioc_time(
|
|
{
|
|
"label": (schema_adjusted.title ?? fallback_label ?? null),
|
|
"hint": (schema_adjusted.description ?? null),
|
|
}
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
/**
|
|
* @todo warning
|
|
*/
|
|
return (
|
|
new class_ioc_text(
|
|
{
|
|
"label": (schema_adjusted.title ?? fallback_label ?? null),
|
|
"hint": (schema_adjusted.description ?? null),
|
|
}
|
|
)
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return (
|
|
new class_ioc_text(
|
|
{
|
|
"label": (schema_adjusted.title ?? fallback_label ?? null),
|
|
"hint": (schema_adjusted.description ?? null),
|
|
}
|
|
)
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
case "array":
|
|
{
|
|
if (! ("items" in schema_adjusted))
|
|
{
|
|
throw (new Error("can not generate array input without 'items' definition"));
|
|
}
|
|
else
|
|
{
|
|
return (
|
|
new class_ioc_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)
|
|
&&
|
|
! (
|
|
("additionalProperties" in schema_adjusted)
|
|
&&
|
|
(schema_adjusted["additionalProperties"] !== false)
|
|
)
|
|
)
|
|
{
|
|
return (
|
|
new class_ioc_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,
|
|
"ioc": 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 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),
|
|
}
|
|
)
|
|
);
|
|
}
|
|
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_ioc_sum(
|
|
formgen.helpers.list.transform<int, {ioc : interface_ioc<any>;}>(
|
|
formgen.helpers.list.sequence(schema_adjusted.oneOf.length),
|
|
(index) => {
|
|
const sub_schema : formgen.helpers.json_schema.type_schema = schema_adjusted.oneOf[index];
|
|
return {
|
|
"ioc": 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_ioc_sum(
|
|
formgen.helpers.list.transform<int, {ioc : interface_ioc<any>;}>(
|
|
formgen.helpers.list.sequence(schema_adjusted.anyOf.length),
|
|
(index) => {
|
|
const sub_schema : formgen.helpers.json_schema.type_schema = schema_adjusted.anyOf[index];
|
|
return {
|
|
"ioc": 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)));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
*/
|
|
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_ioc<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,
|
|
}
|
|
);
|
|
}
|
|
|
|
}
|