UNPKG

windmill-utils-internal

Version:

Internal utility functions for Windmill

251 lines (250 loc) 8.59 kB
const ITEMS_PRESERVED_FIELDS = [ "properties", "required", "additionalProperties", "enum", "resourceType", "contentEncoding", "description", ]; /** * Converts argument signature types to JSON schema properties. * This function handles various Windmill-specific types and converts them * to standard JSON schema format while preserving existing property metadata. * * @param t - The argument signature type definition (can be string or complex object types) * @param oldS - Existing schema property to update with new type information */ export function argSigToJsonSchemaType(t, oldS) { const newS = { type: "" }; if (t === "int") { newS.type = "integer"; } else if (t === "float") { newS.type = "number"; } else if (t === "bool") { newS.type = "boolean"; } else if (t === "email") { newS.type = "string"; newS.format = "email"; } else if (t === "sql") { newS.type = "string"; newS.format = "sql"; } else if (t === "yaml") { newS.type = "string"; newS.format = "yaml"; } else if (t === "bytes") { newS.type = "string"; newS.contentEncoding = "base64"; newS.originalType = "bytes"; } else if (t === "datetime") { newS.type = "string"; newS.format = "date-time"; } else if (typeof t !== "string" && "oneof" in t) { newS.type = "object"; if (t.oneof) { newS.oneOf = t.oneof.map((obj) => { const oldObjS = oldS.oneOf?.find((o) => o?.title === obj.label) ?? undefined; const properties = {}; for (const prop of obj.properties) { if (oldObjS?.properties && prop.key in oldObjS?.properties) { properties[prop.key] = oldObjS?.properties[prop.key]; } else { properties[prop.key] = { description: "", type: "" }; } argSigToJsonSchemaType(prop.typ, properties[prop.key]); } return { type: "object", title: obj.label, properties, order: oldObjS?.order ?? undefined, }; }); } } else if (typeof t !== "string" && `object` in t) { newS.type = "object"; if (t.object.name) { newS.format = `resource-${t.object.name}`; } if (t.object.props) { const properties = {}; for (const prop of t.object.props) { if (oldS.properties && prop.key in oldS.properties) { properties[prop.key] = oldS.properties[prop.key]; } else { properties[prop.key] = { description: "", type: "" }; } argSigToJsonSchemaType(prop.typ, properties[prop.key]); } newS.properties = properties; } } else if (typeof t !== "string" && `str` in t) { newS.type = "string"; if (t.str) { newS.originalType = "enum"; newS.enum = t.str; } else if (oldS.originalType == "string" && oldS.enum) { newS.originalType = "string"; newS.enum = oldS.enum; } else { newS.originalType = "string"; newS.enum = undefined; } } else if (typeof t !== "string" && `resource` in t) { newS.type = "object"; newS.format = `resource-${t.resource}`; } else if (typeof t !== "string" && `dynselect` in t) { newS.type = "object"; newS.format = `dynselect-${t.dynselect}`; } else if (typeof t !== "string" && `dynmultiselect` in t) { newS.type = "object"; newS.format = `dynmultiselect-${t.dynmultiselect}`; } else if (typeof t !== "string" && `list` in t) { newS.type = "array"; if (t.list === "int" || t.list === "float") { newS.items = { type: "number" }; newS.originalType = "number[]"; } else if (t.list === "bytes") { newS.items = { type: "string", contentEncoding: "base64" }; newS.originalType = "bytes[]"; } else if (t.list && typeof t.list == "object" && "str" in t.list && t.list.str) { newS.items = { type: "string", enum: t.list.str }; newS.originalType = "enum[]"; } else if (t.list == "string" || (t.list && typeof t.list == "object" && "str" in t.list)) { newS.items = { type: "string", enum: oldS.items?.enum }; newS.originalType = "string[]"; } else if (t.list && typeof t.list == "object" && "resource" in t.list && t.list.resource) { newS.items = { type: "resource", resourceType: t.list.resource, }; newS.originalType = "resource[]"; } else if (t.list && typeof t.list == "object" && "object" in t.list && t.list.object) { if (t.list.object.name) { newS.format = `resource-${t.list.object.name}`; } if (t.list.object.props && t.list.object.props.length > 0) { const properties = {}; for (const prop of t.list.object.props) { properties[prop.key] = { description: "", type: "" }; argSigToJsonSchemaType(prop.typ, properties[prop.key]); } newS.items = { type: "object", properties: properties }; } else { // Preserve ALL user-defined fields when parser cannot infer structure newS.items = { type: oldS.items?.type || "object" }; if (oldS.items && typeof oldS.items === "object") { ITEMS_PRESERVED_FIELDS.forEach((field) => { if (oldS.items && oldS.items[field] !== undefined) { newS.items[field] = oldS.items[field]; } }); } } newS.originalType = "record[]"; } else { // Preserve ALL user-defined fields for untyped lists (same as record[] branch) newS.items = { type: oldS.items?.type || "object" }; if (oldS.items && typeof oldS.items === "object") { ITEMS_PRESERVED_FIELDS.forEach((field) => { if (oldS.items && oldS.items[field] !== undefined) { newS.items[field] = oldS.items[field]; } }); } newS.originalType = "object[]"; } } else { // Preserve existing type when inference fails, default to "object" for undefined/null newS.type = oldS.type ?? "object"; } const preservedFields = [ "description", "pattern", "min", "max", "currency", "currencyLocale", "multiselect", "customErrorMessage", "required", "showExpr", "password", "order", "dateFormat", "title", "placeholder", ]; preservedFields.forEach((field) => { // @ts-ignore if (oldS[field] !== undefined) { // @ts-ignore newS[field] = oldS[field]; } }); if (oldS.type != newS.type) { for (const prop of Object.getOwnPropertyNames(newS)) { if (prop != "description") { // @ts-ignore delete oldS[prop]; } } } else if ((oldS.format == "date" || oldS.format === "date-time") && newS.format == "string") { newS.format = oldS.format; } else if (newS.format == "date-time" && oldS.format == "date") { newS.format = "date"; } else if (newS.format == "date" || newS.format == "date-time") { newS.format = oldS.format; } else if (oldS.items?.type != newS.items?.type) { delete oldS.items; } else if (oldS.type == "string" && oldS.format != undefined) { newS.format = oldS.format; } if ((oldS.type != newS.type || newS.type != "string") && newS.format == undefined) { oldS.format = undefined; } Object.assign(oldS, newS); }