@autobe/agent
Version:
AI backend server code generator
211 lines (207 loc) • 9.46 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutoBeTestPrepareProgrammer = void 0;
const utils_1 = require("@autobe/utils");
const utils_2 = require("@typia/utils");
const validateEmptyCode_1 = require("../../../utils/validateEmptyCode");
const AutoBeRealizeCollectorProgrammer_1 = require("../../realize/programmers/AutoBeRealizeCollectorProgrammer");
const AutoBeTestFunctionProgrammer_1 = require("./AutoBeTestFunctionProgrammer");
var AutoBeTestPrepareProgrammer;
(function (AutoBeTestPrepareProgrammer) {
/* ----------------------------------------------------------------
GETTERS
---------------------------------------------------------------- */
function is(key, value) {
return (key.endsWith(".ICreate") && utils_2.OpenApiTypeChecker.isObject(value) === true);
}
AutoBeTestPrepareProgrammer.is = is;
function size(document) {
return Object.entries(document.components.schemas).filter(([key, value]) => AutoBeTestPrepareProgrammer.is(key, value)).length;
}
AutoBeTestPrepareProgrammer.size = size;
function getFunctionName(typeName) {
const snake = utils_2.NamingConvention.snake(typeName.split(".")[0].slice(1));
return `prepare_random_${snake}`;
}
AutoBeTestPrepareProgrammer.getFunctionName = getFunctionName;
/* ----------------------------------------------------------------
WRITERS
---------------------------------------------------------------- */
function writeTemplateCode(props) {
return utils_1.StringUtil.trim `
export function ${getFunctionName(props.typeName)}(
input?: DeepPartial<${props.typeName}> | undefined,
): ${props.typeName} {
return {
${Object.keys(props.schema.properties).map((key) => ` ${utils_2.NamingConvention.variable(key) ? key : `[${JSON.stringify(key)}]`}: ...,`)}
};
}
`;
}
AutoBeTestPrepareProgrammer.writeTemplateCode = writeTemplateCode;
function writeNonPropertyCode(props) {
return utils_1.StringUtil.trim `
export function ${getFunctionName(props.typeName)}(
input?: DeepPartial<${props.typeName}> | undefined,
): ${props.typeName} {
input;
return {};
}
`;
}
AutoBeTestPrepareProgrammer.writeNonPropertyCode = writeNonPropertyCode;
function writeStructures(ctx, typeName) {
return __awaiter(this, void 0, void 0, function* () {
return Object.assign(Object.assign({}, (yield AutoBeRealizeCollectorProgrammer_1.AutoBeRealizeCollectorProgrammer.writeStructures(ctx, typeName))), (yield (yield ctx.compiler()).test.getDefaultTypes()));
});
}
AutoBeTestPrepareProgrammer.writeStructures = writeStructures;
/* ----------------------------------------------------------------
COMPILERS
---------------------------------------------------------------- */
function compile(props) {
return __awaiter(this, void 0, void 0, function* () {
const components = {
authorizations: [],
schemas: {},
};
utils_2.OpenApiTypeChecker.visit({
components: props.document.components,
schema: { $ref: `#/components/schemas/${props.procedure.typeName}` },
closure: (s) => {
if (utils_2.OpenApiTypeChecker.isReference(s)) {
const key = s.$ref.split("/").pop();
components.schemas[key] = props.document.components.schemas[key];
}
},
});
return yield AutoBeTestFunctionProgrammer_1.AutoBeTestFunctionProgrammer.compile({
compiler: props.compiler,
document: {
operations: [],
components,
},
function: props.procedure.function,
files: {
[props.procedure.function.location]: props.procedure.function.content,
["src/api/functional/index.ts"]: "export const NO_SDK_FUNCTION_AT_ALL = 1",
},
progress: props.progress,
step: props.step,
});
});
}
AutoBeTestPrepareProgrammer.compile = compile;
function replaceImportStatements(props) {
return __awaiter(this, void 0, void 0, function* () {
let code = yield props.compiler.typescript.removeImportStatements(props.content);
const imports = writeImportStatements(props);
code = [...imports, code].join("\n");
return yield props.compiler.typescript.beautify(code);
});
}
AutoBeTestPrepareProgrammer.replaceImportStatements = replaceImportStatements;
function writeImportStatements(props) {
const typeReferences = new Set();
const visit = (key) => utils_2.OpenApiTypeChecker.visit({
schema: {
$ref: `#/components/schemas/${key}`,
},
components: { schemas: props.schemas },
closure: (next) => {
if (utils_2.OpenApiTypeChecker.isReference(next))
typeReferences.add(next.$ref.split("/").pop().split(".")[0]);
},
});
visit(props.typeName);
const imports = [
`import { ArrayUtil, RandomGenerator } from "@nestia/e2e";`,
`import { randint } from "tstl";`,
`import typia, { tags } from "typia";`,
"",
`import { DeepPartial } from "@ORGANIZATION/PROJECT-api/lib/typings/DeepPartial";`,
`import { IEntity } from "@ORGANIZATION/PROJECT-api/lib/structures/IEntity";`,
...Array.from(typeReferences).map((ref) => `import { ${ref} } from "@ORGANIZATION/PROJECT-api/lib/structures/${ref}";`),
];
return imports;
}
/* ----------------------------------------------------------------
VALIDATORS
---------------------------------------------------------------- */
function validate(props) {
// validate empty code
const functionName = getFunctionName(props.typeName);
const errors = (0, validateEmptyCode_1.validateEmptyCode)({
name: functionName,
asynchronous: false,
draft: props.draft,
revise: props.revise,
path: "$input",
});
// validate property mapping plans
const expected = new Set(Object.keys(props.schema.properties));
const actual = new Set(props.mappings.map((m) => m.property));
if (expected.size === 0 && actual.size !== 0) {
errors.push({
path: `$input.mappings[]`,
value: props.mappings,
expected: "[] // (empty array)",
description: utils_1.StringUtil.trim `
The schema does not have any regular properties to map.
It has only dynamic properties that is represented by
"Record<string, T>" type.
Therefore, the mapping plan must be an empty array.
`,
});
return errors;
}
// must be, but non-existing
for (const e of expected) {
if (actual.has(e) === true)
continue;
errors.push({
path: `$input.mappings[]`,
value: undefined,
expected: utils_1.StringUtil.trim `{
property: ${JSON.stringify(e)},
how: string;
}`,
description: utils_1.StringUtil.trim `
You missed mapping for property ${JSON.stringify(e)}.
Make sure to provide mapping for all properties defined in the schema.
`,
});
}
// must not be, but existing
props.mappings.forEach((m, i) => {
if (expected.has(m.property) === true)
return;
errors.push({
path: `$input.mappings[${i}].property`,
value: m.property,
expected: Array.from(expected)
.map((s) => JSON.stringify(s))
.join(" | "),
description: utils_1.StringUtil.trim `
Property ${JSON.stringify(m.property)} does not exist in the schema.
Actually existing properties are as follows:
${Array.from(expected)
.map((s) => `- ${s}`)
.join("\n")}
`,
});
});
return errors;
}
AutoBeTestPrepareProgrammer.validate = validate;
})(AutoBeTestPrepareProgrammer || (exports.AutoBeTestPrepareProgrammer = AutoBeTestPrepareProgrammer = {}));
//# sourceMappingURL=AutoBeTestPrepareProgrammer.js.map