UNPKG

@autobe/agent

Version:

AI backend server code generator

241 lines (225 loc) 11.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AutoBeInterfaceOperationProgrammer = void 0; const utils_1 = require("@autobe/utils"); const utils_2 = require("@typia/utils"); const AutoBeJsonSchemaValidator_1 = require("../utils/AutoBeJsonSchemaValidator"); var AutoBeInterfaceOperationProgrammer; (function (AutoBeInterfaceOperationProgrammer) { AutoBeInterfaceOperationProgrammer.fix = (operation) => { if (operation.method === "delete" && operation.responseBody !== null) operation.responseBody = null; }; AutoBeInterfaceOperationProgrammer.validate = (props) => { // get method has request body if (props.operation.method === "get" && props.operation.requestBody !== null) props.errors.push({ path: `${props.accessor}.requestBody`, expected: "null (GET method cannot have request body)", value: props.operation.requestBody, description: utils_1.StringUtil.trim ` GET method cannot have request body per HTTP specification. Fix: Change method to "patch" for complex queries, or set requestBody to null. `, }); // operation name if (utils_2.NamingConvention.variable(props.operation.name) === false) props.errors.push({ path: `${props.accessor}.name`, expected: "<valid_variable_name>", value: props.operation.name, description: utils_1.StringUtil.trim ` Operation name "${props.operation.name}" is not a valid JavaScript variable name. It will be used as a controller method name, so it must be a valid identifier. `, }); else if (props.operation.name === "index") { if (props.operation.method !== "patch") props.errors.push({ path: `${props.accessor}.method`, expected: `"patch" when operation name is "index", or change operation name to something else`, value: props.operation.method, description: utils_1.StringUtil.trim ` Operation name "index" is reserved for getting list of resources, or pagination of the resources. Fix: Change method to "patch" when using "index" as operation name. Otherwise, change operation name to something else. `, }); if (props.operation.responseBody === null) props.errors.push({ path: `${props.accessor}.responseBody`, expected: `AutoBeOpenApi.IResponseBody (typeName: "IPageIResource") when operation name is "index"`, value: props.operation.responseBody, description: utils_1.StringUtil.trim ` Operation name "index" is reserved for getting list of resources, so response body must be a paginated type "IPageIResource". Fix: Change response body type to paginated type "IPageIResource", or change operation name to something else. `, }); else if (props.operation.responseBody.typeName.startsWith("IPage") === false) props.errors.push({ path: `${props.accessor}.responseBody.typeName`, expected: `"IPage${props.operation.responseBody.typeName}", or change operation name to something else`, value: props.operation.responseBody.typeName, description: utils_1.StringUtil.trim ` Operation name "index" is reserved for getting list of resources, so response body type must be paginated type "IPageIResource". Fix: Change response body type to paginated type "IPage${props.operation.responseBody.typeName}", or change operation name to something else. `, }); } // validate path parameters match with path validatePathParameters({ errors: props.errors, operation: props.operation, accessor: props.accessor, }); // validate types if (props.operation.requestBody !== null) { validatePrimitiveBody({ kind: "requestBody", errors: props.errors, path: `${props.accessor}.requestBody`, body: props.operation.requestBody, }); AutoBeJsonSchemaValidator_1.AutoBeJsonSchemaValidator.validateKey({ errors: props.errors, path: `${props.accessor}.requestBody.typeName`, key: props.operation.requestBody.typeName, }); } if (props.operation.responseBody !== null) { validatePrimitiveBody({ kind: "responseBody", errors: props.errors, path: `${props.accessor}.responseBody`, body: props.operation.responseBody, }); AutoBeJsonSchemaValidator_1.AutoBeJsonSchemaValidator.validateKey({ errors: props.errors, path: `${props.accessor}.responseBody.typeName`, key: props.operation.responseBody.typeName, }); } }; const validatePathParameters = (props) => { // Check parameter → path matching and uniqueness const parameterNames = new Set(); props.operation.parameters.forEach((p, i) => { // Check if parameter exists in path if (props.operation.path.includes(`{${p.name}}`) === false) props.errors.push({ path: `${props.accessor}.parameters[${i}]`, expected: `removed, or expressed in AutoBeOpenApi.IOperation.path`, value: p, description: utils_1.StringUtil.trim ` Parameter "${p.name}" is defined but not used in path "${props.operation.path}". Fix: Remove parameter at index ${i}, or add {${p.name}} to the path. `, }); parameterNames.add(p.name); }); // Check for duplicate parameter names if (parameterNames.size !== props.operation.parameters.length) props.errors.push({ path: `${props.accessor}.parameters`, expected: `All parameter names must be unique`, value: props.operation.parameters, description: utils_1.StringUtil.trim ` Duplicate parameter names found: ${props.operation.parameters.length} parameters, but only ${parameterNames.size} unique names. Parameters: ${props.operation.parameters.map((p, idx) => `[${idx}]="${p.name}"`).join(", ")} Fix: Remove duplicate parameter definitions. `, }); const symbols = props.operation.path .split("{") .slice(1) .map((s) => s.split("}")[0]); // Check path → parameters matching symbols.forEach((s) => { if (props.operation.parameters.some((p) => p.name === s) === false) props.errors.push({ path: `${props.accessor}.path`, expected: `removed, or defined in AutoBeOpenApi.IOperation.parameters[]`, value: s, description: utils_1.StringUtil.trim ` Path contains "{${s}}" but no corresponding parameter definition exists. Current parameters: ${props.operation.parameters.length === 0 ? "[]" : `[${props.operation.parameters.map((p) => `"${p.name}"`).join(", ")}]`} Fix: Add parameter definition for "${s}", or remove {${s}} from path. `, }); }); // Check for duplicate path parameters const uniqueSymbols = new Set(symbols); if (uniqueSymbols.size !== symbols.length) props.errors.push({ path: `${props.accessor}.path`, expected: `All path parameter names must be unique`, value: props.operation.path, description: utils_1.StringUtil.trim ` Duplicate path parameter names: ${symbols.length} parameters, but only ${uniqueSymbols.size} unique names in "${props.operation.path}". Path parameters: ${symbols.map((s, idx) => `[${idx}]="{${s}}"`).join(", ")} Fix: Rename duplicate parameters to be unique. (e.g., {userId} and {postId} instead of {userId} twice). `, }); }; const validatePrimitiveBody = (props) => { if (props.body.typeName === "undefined" || props.body.typeName === "null") props.errors.push({ path: props.path, value: props.body, expected: "null", description: utils_1.StringUtil.trim ` Type "${props.body.typeName}" is not valid for ${props.kind}. Use null for empty ${props.kind}. `, }); else if (props.body.typeName === "number" || props.body.typeName === "string" || props.body.typeName === "boolean") props.errors.push({ path: `${props.path}.typeName`, value: props.body.typeName, expected: "An object reference type encapsulating the primitive type", description: utils_1.StringUtil.trim ` Primitive type "${props.body.typeName}" not allowed for ${props.kind}. Encapsulate in object type (e.g., I${props.body.typeName[0].toUpperCase()}${props.body.typeName.slice(1)}Value). `, }); else if (props.body.typeName === "object" || props.body.typeName === "any" || props.body.typeName === "interface") props.errors.push({ path: `${props.path}.typeName`, value: props.body.typeName, expected: "An object reference type", description: utils_1.StringUtil.trim ` Type "${props.body.typeName}" is a reserved word. Use a different type name. `, }); else if (props.body.typeName.startsWith("I") === false) { props.errors.push({ path: `${props.path}.typeName`, value: props.body.typeName, expected: "Type name starting with 'I' (e.g., IUser, IProduct, IOrder)", description: utils_1.StringUtil.trim ` Type name "${props.body.typeName}" must start with 'I' prefix per AutoBE naming convention. Fix: Rename to "I${props.body.typeName.charAt(0).toUpperCase()}${props.body.typeName.slice(1)}" (e.g., IUser, IProduct). `, }); } }; })(AutoBeInterfaceOperationProgrammer || (exports.AutoBeInterfaceOperationProgrammer = AutoBeInterfaceOperationProgrammer = {})); //# sourceMappingURL=AutoBeInterfaceOperationProgrammer.js.map