This commit is contained in:
2026-09-02 09:19:43 +03:00
parent 74cb5b6176
commit 962f489142
34 changed files with 1190 additions and 124 deletions
@@ -1,6 +1,6 @@
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { modelToSchema } from '#services/swagger_model'
import { modelToExample } from '#services/swagger_model'
import { ModuleContext } from '#services/module_generator/module_context'
import {
capitalize,
@@ -139,7 +139,7 @@ export async function writeBackendModule(options: WriteBackendModuleOptions) {
snakeCaseName: snake,
name,
snake,
swaggerModel: await modelToSchema(genModel),
swaggerExample: await modelToExample(genModel),
}
writeFileSync(
@@ -150,7 +150,9 @@ export async function writeBackendModule(options: WriteBackendModuleOptions) {
const apiSpec = renderTemplate(join(backendTplDir, 'tests', 'api.spec.hbs'), {
snakeCaseName: snake,
name,
createFields,
updateFields,
})
writeFileSync(paths.testApi, apiSpec, 'utf8')
+32 -4
View File
@@ -1,18 +1,46 @@
const typeMap: Record<string, any> = {
const typeMap: Record<string, { type: string; format?: string }> = {
number: { type: 'integer', format: 'int64' },
string: { type: 'string' },
Date: { type: 'string', format: 'date-time' },
boolean: { type: 'boolean' },
}
/** Legacy schema helper retained for callers that need a property map. */
export async function modelToSchema(model: any) {
const properties: Record<string, any> = {}
const properties: Record<string, unknown> = {}
for (const [key, meta] of model.$columnsDefinitions.entries()) {
const tsType = meta.meta?.designType?.name || 'string'
const mapped = typeMap[tsType] ?? { type: 'string' }
properties[meta?.serializeAs || key] = {
...mapped,
...(typeMap[tsType] ?? { type: 'string' }),
description: key.replace(/([A-Z])/g, ' $1').trim(),
}
}
return JSON.stringify(properties)
}
/**
* Produces a deterministic, concrete JSON object for AutoSwagger response
* annotations. It intentionally omits Lucid columns hidden from serialization.
*/
export async function modelToExample(model: any) {
const example: Record<string, string | number | boolean> = {}
for (const [key, meta] of model.$columnsDefinitions.entries()) {
if (meta.serializeAs === null) continue
const serializedKey = meta.serializeAs || key
const type = meta.meta?.designType?.name || 'string'
example[serializedKey] = sampleValue(serializedKey, type)
}
return JSON.stringify(example)
}
function sampleValue(key: string, type: string): string | number | boolean {
if (type === 'number') return key === 'id' || key.endsWith('_id') ? 42 : 100
if (type === 'boolean') return true
if (type === 'Date') return '2025-01-15T10:30:00.000Z'
if (key.includes('email')) return 'user@example.test'
if (key.includes('url')) return 'https://example.test/resource'
return `Example ${key.replace(/_/g, ' ')}`
}