@udraft/core
Version:
uDraft is a language and stack agnostic code-generation tool that simplifies full-stack development by converting a single YAML file into code for rapid development.
290 lines • 15.3 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
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 });
const renderer_1 = require("../entities/renderer");
const package_1 = require("../helpers/package");
const queries_1 = require("../shortcuts/queries");
const rendering_1 = require("../utils/rendering");
const attributes_1 = require("../shortcuts/attributes");
const missing_attribute_error_1 = require("../errors/missing-attribute-error");
const path = __importStar(require("path"));
const Case = __importStar(require("case"));
const KEYS = {
packageJson: "packageJson",
};
class TSMongooseSchemaRenderer extends renderer_1.URenderer {
constructor(options) {
super("ts@mongoose-schema");
this._schemaDir = "src/schemas";
this._includeModuleInDir = true;
this._updatePackageJson = false;
if (options === null || options === void 0 ? void 0 : options.where)
this._where = options.where;
if (options === null || options === void 0 ? void 0 : options.schemaDir)
this._schemaDir = options.schemaDir;
if (options === null || options === void 0 ? void 0 : options.includeModuleInDir)
this._includeModuleInDir = options.includeModuleInDir;
if (options === null || options === void 0 ? void 0 : options.updatePackageJson)
this._updatePackageJson = options.updatePackageJson;
}
$schema(model) {
var _a;
return (_a = (0, queries_1.$attr)(model, (0, attributes_1._schema)())) !== null && _a !== void 0 ? _a : null;
}
$key(model) {
return this.$schemaName(model);
}
$keys(models) {
return models.map((model) => this.$key(model));
}
$schemaName(model) {
return Case.pascal(model.$name()) + "Schema";
}
$modelName(model) {
return Case.pascal(model.$name()) + "Model";
}
$fileName(model, extension = true) {
return `${Case.kebab(model.$name())}-schema${extension ? ".ts" : ""}`;
}
$fieldName(field) {
return Case.camel(field.$name());
}
$fieldType(field) {
let type = field.$type() + "";
if (type == "reference")
return "mongoose.Schema.ObjectId as any";
if (["int", "float"].includes(type))
return "Number";
if (type !== "nested")
return Case.pascal(type);
}
$fieldDeclaration(field) {
const type = field.$type() + "";
let transformedType = this.$fieldType(field);
let enumModel = null;
if (type == "nested") {
const referencedModel = (0, queries_1.$attr)(field, (0, attributes_1._ref)());
if (referencedModel) {
let enumDefinition = (0, queries_1.$attr)(referencedModel, (0, attributes_1._enum)());
if (enumDefinition) {
transformedType = Case.pascal(typeof Object.values(enumDefinition)[0]);
enumModel = referencedModel;
}
else
transformedType = this.$schemaName(referencedModel);
}
}
let properties = !!(0, queries_1.$attr)(field, (0, attributes_1._array)())
? ` type: [${transformedType}],`
: ` type: ${transformedType},`;
if (enumModel) {
properties += ` enum: ${this._classRenderer.$className(enumModel)},`;
}
if (type == "reference") {
const referencedModel = (0, queries_1.$attr)(field, (0, attributes_1._ref)());
if (referencedModel) {
const schema = (0, queries_1.$attr)(referencedModel, (0, attributes_1._schema)());
if (!schema)
throw new missing_attribute_error_1.MissingAttributeError(referencedModel.$name(), "model", "_schema()");
properties += ` ref: () => ${this.$modelName(referencedModel)},`;
}
}
const addProperty = (key, value) => {
properties += ` ${key}: ${value},`;
};
if (!!(0, queries_1.$attr)(field, (0, attributes_1._required)()))
addProperty("required", "true");
if (!!(0, queries_1.$attr)(field, (0, attributes_1._unique)()))
addProperty("unique", "true");
if (!!(0, queries_1.$attr)(field, (0, attributes_1._index)()))
addProperty("index", (0, queries_1.$attr)(field, (0, attributes_1._index)()));
if ((0, queries_1.$attr)(field, (0, attributes_1._min)()) !== null)
addProperty("min", (0, queries_1.$attr)(field, (0, attributes_1._min)()));
if ((0, queries_1.$attr)(field, (0, attributes_1._max)()) !== null)
addProperty("max", (0, queries_1.$attr)(field, (0, attributes_1._max)()));
if ((0, queries_1.$attr)(field, (0, attributes_1._minLength)()) !== null)
addProperty("minlength", (0, queries_1.$attr)(field, (0, attributes_1._minLength)()));
if ((0, queries_1.$attr)(field, (0, attributes_1._maxLength)()) !== null)
addProperty("maxlength", (0, queries_1.$attr)(field, (0, attributes_1._maxLength)()));
if (!!(0, queries_1.$attr)(field, (0, attributes_1._in)()))
addProperty("enum", JSON.stringify((0, queries_1.$attr)(field, (0, attributes_1._in)())));
if (!!(0, queries_1.$attr)(field, (0, attributes_1._regex)()))
addProperty("match", (0, queries_1.$attr)(field, (0, attributes_1._regex)()).toString());
return ` ${this.$fieldName(field)}: {${properties.replace(/,$/, "")} },\n`;
}
select() {
return __awaiter(this, void 0, void 0, function* () {
this._classRenderer = this.$draft().$requireRenderer(this, "ts@classes");
const models = this.$models(this._where).filter((model) => !!this.$schema(model) &&
!!this._classRenderer.$output(this._classRenderer.$key(model)));
const extraSchemas = [];
models.forEach((model) => {
model.$fields().forEach((field) => {
if (["nested", "reference"].includes(field.$type() + "")) {
const referencedModel = (0, queries_1.$attr)(field, (0, attributes_1._ref)());
if (referencedModel &&
!models.some((m) => m.$name() === referencedModel.$name()) &&
!extraSchemas.includes(referencedModel.$name()) &&
!(0, queries_1.$attr)(referencedModel, (0, attributes_1._enum)())) {
models.push(referencedModel);
extraSchemas.push(referencedModel.$name());
}
}
});
});
const paths = [];
if (this._updatePackageJson)
paths.push({
key: KEYS.packageJson,
path: "package.json",
});
models.forEach((model) => {
if (paths.some((p) => p.key === this.$key(model)))
return;
const mod = (0, queries_1.$attr)(model, (0, attributes_1._rootModule)());
paths.push({
key: this.$key(model),
path: path.join(this._schemaDir, this._includeModuleInDir ? Case.kebab(mod ? mod.$name() : "") : "", this.$fileName(model)),
});
});
return {
paths,
models,
};
});
}
render() {
return __awaiter(this, void 0, void 0, function* () {
const output = [];
if (this._updatePackageJson)
output.push({
key: KEYS.packageJson,
content: (0, package_1.addPackageJsonDependency)(this.$content("packageJson").content, [
{
name: "mongoose",
version: "^8.11.0",
},
]),
});
const models = this.$selection().models || [];
models.forEach((model) => {
const modelKey = this._classRenderer.$key(model);
const schemaKey = this.$key(model);
const classPath = this._classRenderer.$path(modelKey);
const schemaPath = this.$path(schemaKey);
if (!schemaPath || !classPath)
return;
const importCursor = "#import-cursor\n";
const fieldCursor = "#field-cursor\n";
const optionsCursor = "#options-cursor\n";
const textIndexCursor = "#text-index-cursor\n";
let content = `import mongoose from "mongoose";\nimport { ${this._classRenderer.$className(model)} } from "${this.$resolveRelativePath(schemaPath.path, classPath.path).replace(".ts", "")}";\n${importCursor}\n` +
`export const ${this.$schemaName(model)} = new mongoose.Schema<${this._classRenderer.$className(model)}>({\n${fieldCursor}}${optionsCursor});${textIndexCursor}`;
if ((0, queries_1.$attr)(model, (0, attributes_1._schema)()))
content += `\n\nexport const ${this.$modelName(model)} = mongoose.model<${this._classRenderer.$className(model)}>("${(0, queries_1.$attr)(model, (0, attributes_1._schema)())}", ${this.$schemaName(model)});`;
const fields = model.$fields();
const importedSchemas = [];
let disableNoExplicityAny = false;
const textIndexes = [];
const customTextIndexes = (0, queries_1.$attr)(model, (0, attributes_1._textIndex)());
if (customTextIndexes && Array.isArray(customTextIndexes))
textIndexes.push(...customTextIndexes);
fields.forEach((field) => {
if (field.$name() == "_id" || (0, queries_1.$attr)(field, (0, attributes_1._virtual)()))
return;
const fieldDeclaration = this.$fieldDeclaration(field);
if (!!(0, queries_1.$attr)(field, (0, attributes_1._textIndex)()))
textIndexes.push(field.$name());
if (["nested", "reference"].includes(field.$type() + "")) {
const referencedModel = (0, queries_1.$attr)(field, (0, attributes_1._ref)());
if (referencedModel) {
if (this.$schemaName(model) != this.$schemaName(referencedModel) &&
!importedSchemas.includes(this.$schemaName(referencedModel))) {
const isRefId = field.$type() == "reference";
const enumDefinition = (0, queries_1.$attr)(referencedModel, (0, attributes_1._enum)());
if (isRefId)
disableNoExplicityAny = true;
content = (0, rendering_1.writeToCursor)(importCursor, `import { ${isRefId
? this.$modelName(referencedModel)
: enumDefinition
? this._classRenderer.$className(referencedModel)
: this.$schemaName(referencedModel)} } from "${this.$resolveRelativePath(schemaPath.path, (enumDefinition
? this._classRenderer.$path(this._classRenderer.$key(referencedModel))
: this.$path(this.$key(referencedModel))).path).replace(".ts", "")}";\n`, content);
importedSchemas.push(this.$schemaName(referencedModel));
}
}
}
content = (0, rendering_1.writeToCursor)(fieldCursor, fieldDeclaration, content);
});
if (!!(0, queries_1.$attr)(model, (0, attributes_1._noId)())) {
content = (0, rendering_1.writeToCursor)(optionsCursor, `,\n{ _id: false }\n`, content);
}
if (textIndexes.length > 0) {
content = (0, rendering_1.writeToCursor)(textIndexCursor, `\n\n${this.$schemaName(model)}.index({ ` +
textIndexes
.map((textIndex) => `"${textIndex}": "text"`)
.join(", ") +
`});`, content);
}
content = (0, rendering_1.closeCursor)(fieldCursor, content);
content = (0, rendering_1.closeCursor)(importCursor, content);
content = (0, rendering_1.closeCursor)(optionsCursor, content);
content = (0, rendering_1.closeCursor)(textIndexCursor, content);
if (disableNoExplicityAny) {
content =
"/* eslint-disable @typescript-eslint/no-explicit-any */\n\n" +
content;
}
output.push({
key: schemaKey,
content,
});
});
return output;
});
}
}
exports.default = TSMongooseSchemaRenderer;
//# sourceMappingURL=ts-mongoose-schema-renderer.js.map