zeti-framework-backend 0.3.0 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-6Q7CWKSA.js → chunk-MXFWPHXO.js} +17 -22
- package/dist/chunk-MXFWPHXO.js.map +1 -0
- package/dist/{chunk-TTILJJ3O.js → chunk-O3LUZPTQ.js} +2 -1
- package/dist/{chunk-TTILJJ3O.js.map → chunk-O3LUZPTQ.js.map} +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/{generator-KC24DE6M.js → generator-4OQC53GR.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/scripts/index.js +1 -1
- package/dist/swagger/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-6Q7CWKSA.js.map +0 -1
- /package/dist/{generator-KC24DE6M.js.map → generator-4OQC53GR.js.map} +0 -0
|
@@ -369,13 +369,23 @@ ${sortedNames.map((name) => ` ${name}: _${name},`).join("\n")}
|
|
|
369
369
|
` : `export const namedSchemas = {} as const;
|
|
370
370
|
|
|
371
371
|
`;
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
if (
|
|
375
|
-
|
|
372
|
+
const routesByPath = /* @__PURE__ */ new Map();
|
|
373
|
+
for (const route of routes) {
|
|
374
|
+
if (!routesByPath.has(route.path)) {
|
|
375
|
+
routesByPath.set(route.path, []);
|
|
376
376
|
}
|
|
377
|
-
|
|
378
|
-
|
|
377
|
+
routesByPath.get(route.path).push(route);
|
|
378
|
+
}
|
|
379
|
+
const routeSchemasOutput = Array.from(routesByPath.entries()).map(([path4, pathRoutes]) => {
|
|
380
|
+
const methods = pathRoutes.map((r) => {
|
|
381
|
+
const hasFormDataStr = r.hasFormData ? ", hasFormData: true" : "";
|
|
382
|
+
if (r.schemaName) {
|
|
383
|
+
return `"${r.method}": { schema: _${r.schemaName}, ref: "${r.schemaName}"${hasFormDataStr} }`;
|
|
384
|
+
}
|
|
385
|
+
const fixedReturnType = r.returnType.replace(/namedSchemas\.([A-Z]\w*)/g, "_$1");
|
|
386
|
+
return `"${r.method}": { schema: ${fixedReturnType}, ref: null${hasFormDataStr} }`;
|
|
387
|
+
}).join(", ");
|
|
388
|
+
return ` "${path4}": { ${methods} },`;
|
|
379
389
|
}).join("\n");
|
|
380
390
|
const output = `// Auto-generated by @zeti/framework/scripts
|
|
381
391
|
// Do not edit manually
|
|
@@ -507,7 +517,6 @@ import type { Context, Next } from 'hono';
|
|
|
507
517
|
import type { PrismaClient } from '@prisma/client';
|
|
508
518
|
import {
|
|
509
519
|
getPrismaClient as _getPrismaClient,
|
|
510
|
-
getSpecialDatabase as _getSpecialDatabase,
|
|
511
520
|
createMiddleware as _createMiddleware,
|
|
512
521
|
} from 'zeti-framework-backend';
|
|
513
522
|
import type { MiddlewareHandler as _MiddlewareHandler } from 'zeti-framework-backend';
|
|
@@ -590,20 +599,6 @@ export function createMiddlewareFactory<T extends any[]>(
|
|
|
590
599
|
export function getPrismaClient(tenantId?: string): PrismaClient {
|
|
591
600
|
return _getPrismaClient<PrismaClient>(tenantId);
|
|
592
601
|
}
|
|
593
|
-
|
|
594
|
-
/**
|
|
595
|
-
* Retorna um database especial com tipagem correta
|
|
596
|
-
*
|
|
597
|
-
* @param key - Chave do database especial configurado em specialDatabases
|
|
598
|
-
* @returns PrismaClient tipado
|
|
599
|
-
*
|
|
600
|
-
* @example
|
|
601
|
-
* const adminDb = getSpecialDatabase('admin');
|
|
602
|
-
* const logs = await adminDb.auditLog.findMany();
|
|
603
|
-
*/
|
|
604
|
-
export function getSpecialDatabase(key: string): PrismaClient {
|
|
605
|
-
return _getSpecialDatabase<PrismaClient>(key);
|
|
606
|
-
}
|
|
607
602
|
`;
|
|
608
603
|
async function ensureAppFile(zetiDir, prismaImport) {
|
|
609
604
|
const appPath = path3.join(zetiDir, "app.ts");
|
|
@@ -687,4 +682,4 @@ export {
|
|
|
687
682
|
generateSwaggerTypes,
|
|
688
683
|
runPrebuild
|
|
689
684
|
};
|
|
690
|
-
//# sourceMappingURL=chunk-
|
|
685
|
+
//# sourceMappingURL=chunk-MXFWPHXO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/scripts/generate-registry.ts","../src/scripts/generate-swagger-types.ts","../src/scripts/run-prebuild.ts"],"sourcesContent":["import path from 'path';\n\nexport interface GenerateRegistryOptions {\n controllersPath: string;\n indexPath: string;\n startMarker?: string;\n endMarker?: string;\n /** Se true, escreve apenas os imports no arquivo (para .zeti/registry.ts) */\n outputMode?: 'inject' | 'standalone';\n}\n\nexport async function generateRegistry(options: GenerateRegistryOptions) {\n const {\n controllersPath,\n indexPath,\n startMarker = '// @CONTROLLERS_START',\n endMarker = '// @CONTROLLERS_END',\n outputMode = 'inject',\n } = options;\n\n // Usa Bun.Glob para listar arquivos (mais rápido)\n const glob = new Bun.Glob('**/*.ts');\n const imports: string[] = [];\n\n for await (const file of glob.scan({ cwd: controllersPath, absolute: true })) {\n const name = path.basename(file);\n if (name === 'index.ts' || name === 'registry.ts') continue;\n\n const relativePath = path.relative(path.dirname(indexPath), file);\n const importPath = relativePath.replace(/\\\\/g, '/').replace(/\\.ts$/, '');\n imports.push(`import \"${importPath.startsWith('.') ? importPath : './' + importPath}\";`);\n }\n\n if (outputMode === 'standalone') {\n const content = `// Generated by zeti-framework-backend. Do not edit.\n\n${imports.join('\\n')}\n`;\n\n // Só escreve se o conteúdo mudou\n const file = Bun.file(indexPath);\n try {\n if (await file.exists()) {\n const existing = await file.text();\n if (existing === content) {\n console.log(`✅ Registry unchanged (${imports.length} controllers)`);\n return;\n }\n }\n } catch {\n // Arquivo não existe\n }\n\n await Bun.write(indexPath, content);\n console.log(`✅ Generated .zeti/registry.ts with ${imports.length} controller imports`);\n return;\n }\n\n // Modo inject\n const file = Bun.file(indexPath);\n const indexContent = await file.exists() ? await file.text() : '';\n\n const generatedBlock = `${startMarker}\\n${imports.join('\\n')}\\n${endMarker}`;\n\n let newContent: string;\n if (indexContent.includes(startMarker)) {\n const regex = new RegExp(`${startMarker}[\\\\s\\\\S]*?${endMarker}`, 'g');\n newContent = indexContent.replace(regex, generatedBlock);\n } else {\n newContent = indexContent + (indexContent ? '\\n\\n' : '') + generatedBlock;\n }\n\n // Só escreve se o conteúdo mudou\n if (newContent !== indexContent) {\n await Bun.write(indexPath, newContent);\n console.log(`✅ Injected ${imports.length} controller imports into ${indexPath}`);\n } else {\n console.log(`✅ Registry unchanged (${imports.length} controllers)`);\n }\n}\n","import path from 'path';\n\nexport interface GenerateSwaggerTypesOptions {\n controllersPath: string;\n outputPath: string;\n}\n\ninterface RouteInfo {\n path: string;\n method: string;\n returnType: string;\n schemaName?: string;\n hasFormData?: boolean;\n}\n\n// Divide um union type corretamente, respeitando aninhamento\nfunction splitUnionType(typeStr: string): string[] {\n const parts: string[] = [];\n let depth = 0;\n let current = '';\n \n for (let i = 0; i < typeStr.length; i++) {\n const char = typeStr[i];\n if (char === '<' || char === '{' || char === '[' || char === '(') depth++;\n else if (char === '>' || char === '}' || char === ']' || char === ')') depth--;\n else if (char === '|' && depth === 0) {\n if (current.trim()) parts.push(current.trim());\n current = '';\n continue;\n }\n current += char;\n }\n if (current.trim()) parts.push(current.trim());\n \n return parts;\n}\n\n// Converte tipo TypeScript para Zod schema, usando referências para tipos nomeados\nfunction typeToZodSchemaWithRefs(\n typeStr: string, \n typeDefinitions: Map<string, string>, \n namedSchemas: Map<string, string>,\n depth = 0\n): string {\n if (depth > 10) return 'z.any()';\n \n typeStr = typeStr.trim();\n \n // Remove Promise wrapper\n const promiseMatch = typeStr.match(/^Promise<(.+)>$/);\n if (promiseMatch) {\n typeStr = promiseMatch[1].trim();\n }\n \n // Tipos primitivos\n if (typeStr === 'string') return 'z.string()';\n if (typeStr === 'number') return 'z.number()';\n if (typeStr === 'boolean') return 'z.boolean()';\n if (typeStr === 'null') return 'z.null()';\n if (typeStr === 'undefined') return 'z.undefined()';\n if (typeStr === 'any') return 'z.any()';\n if (typeStr === 'unknown') return 'z.unknown()';\n if (typeStr === 'void') return 'z.void()';\n if (typeStr === 'Date') return 'z.date()';\n \n // String literal\n const stringLiteralMatch = typeStr.match(/^[\"'](.+)[\"']$/);\n if (stringLiteralMatch) {\n return `z.literal(\"${stringLiteralMatch[1]}\")`;\n }\n \n // Number literal\n if (/^\\d+$/.test(typeStr)) {\n return `z.literal(${typeStr})`;\n }\n \n // Array com tipo nomeado: TypeName[]\n const arrayNamedMatch = typeStr.match(/^(\\w+)\\[\\]$/);\n if (arrayNamedMatch) {\n const itemType = arrayNamedMatch[1];\n if (typeDefinitions.has(itemType)) {\n // Garante que o tipo referenciado seja processado\n if (!namedSchemas.has(itemType)) {\n const typeDef = typeDefinitions.get(itemType)!;\n namedSchemas.set(itemType, typeToZodSchemaWithRefs(typeDef, typeDefinitions, namedSchemas, depth + 1));\n }\n return `z.array(namedSchemas.${itemType})`;\n }\n return `z.array(${typeToZodSchemaWithRefs(itemType, typeDefinitions, namedSchemas, depth + 1)})`;\n }\n \n // Array genérico: Array<Type>\n const arrayGenericMatch = typeStr.match(/^Array<(.+)>$/);\n if (arrayGenericMatch) {\n const itemType = arrayGenericMatch[1].trim();\n if (typeDefinitions.has(itemType)) {\n if (!namedSchemas.has(itemType)) {\n const typeDef = typeDefinitions.get(itemType)!;\n namedSchemas.set(itemType, typeToZodSchemaWithRefs(typeDef, typeDefinitions, namedSchemas, depth + 1));\n }\n return `z.array(namedSchemas.${itemType})`;\n }\n return `z.array(${typeToZodSchemaWithRefs(itemType, typeDefinitions, namedSchemas, depth + 1)})`;\n }\n \n // Verifica se é uma referência a um tipo definido\n if (/^[A-Z]\\w*$/.test(typeStr) && typeDefinitions.has(typeStr)) {\n // Garante que o tipo referenciado seja processado\n if (!namedSchemas.has(typeStr)) {\n const typeDef = typeDefinitions.get(typeStr)!;\n namedSchemas.set(typeStr, typeToZodSchemaWithRefs(typeDef, typeDefinitions, namedSchemas, depth + 1));\n }\n return `namedSchemas.${typeStr}`;\n }\n \n // Object inline { key: type, ... }\n if (typeStr.startsWith('{') && typeStr.endsWith('}')) {\n const inner = typeStr.slice(1, -1).trim();\n if (!inner) return 'z.object({})';\n \n const props: string[] = [];\n let currentDepth = 0;\n let current = '';\n let inString = false;\n let stringChar = '';\n \n for (let i = 0; i < inner.length; i++) {\n const char = inner[i];\n \n if (!inString && (char === '\"' || char === \"'\" || char === '`')) {\n inString = true;\n stringChar = char;\n current += char;\n } else if (inString && char === stringChar && inner[i - 1] !== '\\\\') {\n inString = false;\n current += char;\n } else if (!inString) {\n if (char === '{' || char === '<' || char === '[' || char === '(') currentDepth++;\n else if (char === '}' || char === '>' || char === ']' || char === ')') currentDepth--;\n \n if ((char === ',' || char === ';') && currentDepth === 0) {\n if (current.trim()) props.push(current.trim());\n current = '';\n } else {\n current += char;\n }\n } else {\n current += char;\n }\n }\n if (current.trim()) props.push(current.trim());\n \n const zodProps = props.map(prop => {\n let colonIndex = -1;\n let propDepth = 0;\n for (let i = 0; i < prop.length; i++) {\n const char = prop[i];\n if (char === '<' || char === '{' || char === '[') propDepth++;\n else if (char === '>' || char === '}' || char === ']') propDepth--;\n else if (char === ':' && propDepth === 0) {\n colonIndex = i;\n break;\n }\n }\n \n if (colonIndex === -1) return null;\n \n let key = prop.slice(0, colonIndex).trim();\n const value = prop.slice(colonIndex + 1).trim();\n \n const isOptional = key.endsWith('?');\n if (isOptional) key = key.slice(0, -1);\n \n const zodType = typeToZodSchemaWithRefs(value, typeDefinitions, namedSchemas, depth + 1);\n return `${key}: ${isOptional ? `${zodType}.optional()` : zodType}`;\n }).filter(Boolean);\n \n return `z.object({ ${zodProps.join(', ')} })`;\n }\n \n // Union type\n if (typeStr.includes('|') && !typeStr.includes('{')) {\n const types = splitUnionType(typeStr).map(t => typeToZodSchemaWithRefs(t.trim(), typeDefinitions, namedSchemas, depth + 1));\n if (types.length === 2 && types.includes('z.undefined()')) {\n const other = types.find(t => t !== 'z.undefined()');\n return `${other}.optional()`;\n }\n if (types.length === 2 && types.includes('z.null()')) {\n const other = types.find(t => t !== 'z.null()');\n return `${other}.nullable()`;\n }\n return `z.union([${types.join(', ')}])`;\n }\n\n // Referência a tipo não encontrado\n if (/^[A-Z]\\w*$/.test(typeStr)) {\n return 'z.any()';\n }\n\n return 'z.any()';\n}\n\n// Converte tipo TypeScript inline para Zod schema (versão sem referências - para compatibilidade)\nfunction typeToZodSchema(typeStr: string, typeDefinitions: Map<string, string>, depth = 0): string {\n if (depth > 10) return 'z.any()'; // Previne recursão infinita\n \n typeStr = typeStr.trim();\n \n // Remove Promise wrapper\n const promiseMatch = typeStr.match(/^Promise<(.+)>$/);\n if (promiseMatch) {\n typeStr = promiseMatch[1].trim();\n }\n \n // Tipos primitivos\n if (typeStr === 'string') return 'z.string()';\n if (typeStr === 'number') return 'z.number()';\n if (typeStr === 'boolean') return 'z.boolean()';\n if (typeStr === 'null') return 'z.null()';\n if (typeStr === 'undefined') return 'z.undefined()';\n if (typeStr === 'any') return 'z.any()';\n if (typeStr === 'unknown') return 'z.unknown()';\n if (typeStr === 'void') return 'z.void()';\n if (typeStr === 'Date') return 'z.date()';\n \n // String literal\n const stringLiteralMatch = typeStr.match(/^[\"'](.+)[\"']$/);\n if (stringLiteralMatch) {\n return `z.literal(\"${stringLiteralMatch[1]}\")`;\n }\n \n // Number literal\n if (/^\\d+$/.test(typeStr)) {\n return `z.literal(${typeStr})`;\n }\n \n // Array\n const arrayMatch = typeStr.match(/^(.+)\\[\\]$/) || typeStr.match(/^Array<(.+)>$/);\n if (arrayMatch) {\n return `z.array(${typeToZodSchema(arrayMatch[1], typeDefinitions, depth + 1)})`;\n }\n \n // Verifica se é uma referência a um tipo definido (antes de processar como objeto)\n if (/^[A-Z]\\w*$/.test(typeStr) && typeDefinitions.has(typeStr)) {\n const typeDef = typeDefinitions.get(typeStr)!;\n return typeToZodSchema(typeDef, typeDefinitions, depth + 1);\n }\n \n // Object inline { key: type, ... }\n if (typeStr.startsWith('{') && typeStr.endsWith('}')) {\n const inner = typeStr.slice(1, -1).trim();\n if (!inner) return 'z.object({})';\n \n const props: string[] = [];\n let currentDepth = 0;\n let current = '';\n let inString = false;\n let stringChar = '';\n \n for (let i = 0; i < inner.length; i++) {\n const char = inner[i];\n \n if (!inString && (char === '\"' || char === \"'\" || char === '`')) {\n inString = true;\n stringChar = char;\n current += char;\n } else if (inString && char === stringChar && inner[i - 1] !== '\\\\') {\n inString = false;\n current += char;\n } else if (!inString) {\n if (char === '{' || char === '<' || char === '[' || char === '(') currentDepth++;\n else if (char === '}' || char === '>' || char === ']' || char === ')') currentDepth--;\n \n if ((char === ',' || char === ';') && currentDepth === 0) {\n if (current.trim()) props.push(current.trim());\n current = '';\n } else {\n current += char;\n }\n } else {\n current += char;\n }\n }\n if (current.trim()) props.push(current.trim());\n \n const zodProps = props.map(prop => {\n // Encontra o primeiro : que não está dentro de um tipo genérico\n let colonIndex = -1;\n let depth = 0;\n for (let i = 0; i < prop.length; i++) {\n const char = prop[i];\n if (char === '<' || char === '{' || char === '[') depth++;\n else if (char === '>' || char === '}' || char === ']') depth--;\n else if (char === ':' && depth === 0) {\n colonIndex = i;\n break;\n }\n }\n \n if (colonIndex === -1) return null;\n \n let key = prop.slice(0, colonIndex).trim();\n const value = prop.slice(colonIndex + 1).trim();\n \n const isOptional = key.endsWith('?');\n if (isOptional) key = key.slice(0, -1);\n \n const zodType = typeToZodSchema(value, typeDefinitions, depth + 1);\n return `${key}: ${isOptional ? `${zodType}.optional()` : zodType}`;\n }).filter(Boolean);\n \n return `z.object({ ${zodProps.join(', ')} })`;\n }\n \n // Union type\n if (typeStr.includes('|') && !typeStr.includes('{')) {\n const types = splitUnionType(typeStr).map(t => typeToZodSchema(t.trim(), typeDefinitions, depth + 1));\n if (types.length === 2 && types.includes('z.undefined()')) {\n const other = types.find(t => t !== 'z.undefined()');\n return `${other}.optional()`;\n }\n if (types.length === 2 && types.includes('z.null()')) {\n const other = types.find(t => t !== 'z.null()');\n return `${other}.nullable()`;\n }\n return `z.union([${types.join(', ')}])`;\n }\n \n // Intersection type\n if (typeStr.includes('&') && !typeStr.includes('{')) {\n const types = typeStr.split('&').map(t => typeToZodSchema(t.trim(), typeDefinitions, depth + 1));\n return `z.intersection(${types.join(', ')})`;\n }\n \n // Referência a tipo não encontrado - retorna z.any()\n if (/^[A-Z]\\w*$/.test(typeStr)) {\n return 'z.any()';\n }\n \n return 'z.any()';\n}\n\n// Extrai definições de tipos do arquivo (suporta tipos aninhados)\nfunction extractTypeDefinitions(content: string): Map<string, string> {\n const types = new Map<string, string>();\n \n // Remove comentários para evitar falsos positivos\n const cleanContent = content\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/\\/\\/.*$/gm, '');\n \n // Captura: type Name = { ... } ou interface Name { ... }\n // Usa uma abordagem mais robusta para capturar objetos aninhados\n const typeRegex = /(?:export\\s+)?(?:type|interface)\\s+(\\w+)\\s*=?\\s*\\{/g;\n \n let match;\n while ((match = typeRegex.exec(cleanContent)) !== null) {\n const name = match[1];\n const startIndex = match.index + match[0].length - 1; // Posição do {\n \n // Encontra o } correspondente\n let depth = 1;\n let endIndex = startIndex + 1;\n \n while (depth > 0 && endIndex < cleanContent.length) {\n const char = cleanContent[endIndex];\n if (char === '{') depth++;\n else if (char === '}') depth--;\n endIndex++;\n }\n \n const body = cleanContent.slice(startIndex, endIndex);\n types.set(name, body);\n }\n \n return types;\n}\n\n// Extrai rotas usando regex (muito mais rápido que TypeScript parser)\nfunction extractRoutes(\n content: string, \n typeDefinitions: Map<string, string>,\n namedSchemas: Map<string, string>\n): RouteInfo[] {\n const routes: RouteInfo[] = [];\n \n // Regex para capturar app.get/post/etc ou get/post/etc\n const routeRegex = /(?:app\\.)?(get|post|put|del|patch)\\s*\\(\\s*[\"'`]([^\"'`]+)[\"'`]/g;\n \n let match;\n while ((match = routeRegex.exec(content)) !== null) {\n const [fullMatch, method, routePath] = match;\n \n // Procura o bloco da rota após o match\n const afterMatch = content.slice(match.index + fullMatch.length, match.index + fullMatch.length + 2000);\n \n let returnType = 'z.any()';\n let schemaName: string | undefined;\n \n // Tenta encontrar tipo explícito: Promise<TypeName> ou Promise<{...}>\n const explicitTypeMatch = afterMatch.match(/route\\s*:\\s*async\\s*\\([^)]*\\)\\s*:\\s*Promise\\s*<([^>]+)>/);\n if (explicitTypeMatch) {\n const typeRef = explicitTypeMatch[1].trim();\n \n // Verifica se é uma referência a um tipo definido\n if (typeDefinitions.has(typeRef)) {\n // Garante que o tipo seja processado com referências\n if (!namedSchemas.has(typeRef)) {\n const typeDef = typeDefinitions.get(typeRef)!;\n namedSchemas.set(typeRef, typeToZodSchemaWithRefs(typeDef, typeDefinitions, namedSchemas));\n }\n returnType = `namedSchemas.${typeRef}`;\n schemaName = typeRef;\n } else {\n // Tipo inline\n returnType = typeToZodSchemaWithRefs(typeRef, typeDefinitions, namedSchemas);\n }\n } else {\n // Tenta inferir do return statement\n const returnMatch = afterMatch.match(/return\\s+(\\{[^}]+\\})/);\n if (returnMatch) {\n returnType = inferTypeFromValue(returnMatch[1]);\n }\n }\n\n routes.push({\n path: routePath,\n method: method === 'del' ? 'delete' : method,\n returnType,\n schemaName,\n hasFormData: content.includes('formData'),\n });\n }\n \n return routes;\n}\n\n// Infere tipo Zod a partir de um valor literal\nfunction inferTypeFromValue(value: string): string {\n value = value.trim();\n \n // Objeto literal\n if (value.startsWith('{') && value.endsWith('}')) {\n const inner = value.slice(1, -1).trim();\n if (!inner) return 'z.object({})';\n \n const props: string[] = [];\n \n // Parse simples de propriedades\n const propRegex = /(\\w+)\\s*:\\s*(\"[^\"]*\"|'[^']*'|`[^`]*`|\\d+|true|false|null|\\{[^}]*\\}|\\[[^\\]]*\\])/g;\n let propMatch;\n \n while ((propMatch = propRegex.exec(inner)) !== null) {\n const [, key, val] = propMatch;\n const zodType = inferTypeFromValue(val);\n props.push(`${key}: ${zodType}`);\n }\n \n if (props.length > 0) {\n return `z.object({ ${props.join(', ')} })`;\n }\n }\n \n // String literal\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\")) ||\n (value.startsWith('`') && value.endsWith('`'))) {\n return 'z.string()';\n }\n \n // Number\n if (/^\\d+(\\.\\d+)?$/.test(value)) {\n return 'z.number()';\n }\n \n // Boolean\n if (value === 'true' || value === 'false') {\n return 'z.boolean()';\n }\n \n // Null\n if (value === 'null') {\n return 'z.null()';\n }\n \n // Array\n if (value.startsWith('[') && value.endsWith(']')) {\n return 'z.array(z.any())';\n }\n \n return 'z.any()';\n}\n\nexport async function generateSwaggerTypes(options: GenerateSwaggerTypesOptions) {\n const { controllersPath, outputPath } = options;\n\n const routes: RouteInfo[] = [];\n const namedSchemas: Map<string, string> = new Map();\n\n // Usa Bun.Glob para listar arquivos\n const glob = new Bun.Glob('**/*.ts');\n const files: string[] = [];\n \n for await (const file of glob.scan({ cwd: controllersPath, absolute: true })) {\n const name = path.basename(file);\n if (name !== 'index.ts' && name !== 'registry.ts') {\n files.push(file);\n }\n }\n \n // Processa todos os arquivos em paralelo usando Bun.file\n await Promise.all(files.map(async (filePath) => {\n const file = Bun.file(filePath);\n const content = await file.text();\n \n // Extrai definições de tipos do arquivo\n const typeDefinitions = extractTypeDefinitions(content);\n \n // Adiciona TODOS os tipos definidos como schemas nomeados\n for (const [typeName, typeDef] of typeDefinitions) {\n if (!namedSchemas.has(typeName)) {\n const zodSchema = typeToZodSchemaWithRefs(typeDef, typeDefinitions, namedSchemas);\n namedSchemas.set(typeName, zodSchema);\n }\n }\n \n // Extrai rotas passando as definições de tipos\n const fileRoutes = extractRoutes(content, typeDefinitions, namedSchemas);\n \n routes.push(...fileRoutes);\n }));\n\n await writeOutput(outputPath, routes, namedSchemas);\n}\n\n// Ordena schemas por dependência (topological sort)\nfunction sortSchemasByDependency(schemas: Map<string, string>): string[] {\n const sorted: string[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n \n function getDependencies(schema: string): string[] {\n const deps: string[] = [];\n // Procura por referências a outros schemas: namedSchemas.TypeName ou _TypeName\n const refMatches = schema.matchAll(/(?:namedSchemas\\.|_)([A-Z]\\w*)/g);\n for (const match of refMatches) {\n if (schemas.has(match[1])) {\n deps.push(match[1]);\n }\n }\n return deps;\n }\n \n function visit(name: string) {\n if (visited.has(name)) return;\n if (visiting.has(name)) return; // Ciclo detectado, ignora\n \n visiting.add(name);\n const schema = schemas.get(name);\n if (schema) {\n for (const dep of getDependencies(schema)) {\n visit(dep);\n }\n }\n visiting.delete(name);\n visited.add(name);\n sorted.push(name);\n }\n \n for (const name of schemas.keys()) {\n visit(name);\n }\n \n return sorted;\n}\n\nasync function writeOutput(outputPath: string, routes: RouteInfo[], namedSchemas: Map<string, string>) {\n const namedSchemasEntries = Array.from(namedSchemas.entries());\n \n // Ordena schemas por dependência\n const sortedNames = sortSchemasByDependency(namedSchemas);\n \n // Gera cada schema como uma variável separada (para evitar referência circular)\n const schemaDeclarations = sortedNames.map(name => {\n const schema = namedSchemas.get(name)!;\n // Substitui namedSchemas.X por _X (variável local)\n const fixedSchema = schema.replace(/namedSchemas\\.([A-Z]\\w*)/g, '_$1');\n return `const _${name} = ${fixedSchema};`;\n }).join('\\n');\n \n // Gera o objeto namedSchemas referenciando as variáveis\n const namedSchemasOutput = namedSchemasEntries.length > 0\n ? `export const namedSchemas = {\\n${sortedNames.map(name => ` ${name}: _${name},`).join('\\n')}\\n} as const;\\n\\n`\n : `export const namedSchemas = {} as const;\\n\\n`;\n\n // Agrupa rotas por path para evitar duplicação de chaves\n const routesByPath = new Map<string, RouteInfo[]>();\n for (const route of routes) {\n if (!routesByPath.has(route.path)) {\n routesByPath.set(route.path, []);\n }\n routesByPath.get(route.path)!.push(route);\n }\n\n const routeSchemasOutput = Array.from(routesByPath.entries()).map(([path, pathRoutes]) => {\n const methods = pathRoutes.map((r) => {\n const hasFormDataStr = r.hasFormData ? ', hasFormData: true' : '';\n if (r.schemaName) {\n return `\"${r.method}\": { schema: _${r.schemaName}, ref: \"${r.schemaName}\"${hasFormDataStr} }`;\n }\n // Substitui namedSchemas.X por _X no returnType também\n const fixedReturnType = r.returnType.replace(/namedSchemas\\.([A-Z]\\w*)/g, '_$1');\n return `\"${r.method}\": { schema: ${fixedReturnType}, ref: null${hasFormDataStr} }`;\n }).join(', ');\n \n return ` \"${path}\": { ${methods} },`;\n }).join('\\n');\n\n const output = `// Auto-generated by @zeti/framework/scripts\n// Do not edit manually\n\nimport { z } from \"zod\";\n\n${schemaDeclarations}\n\n${namedSchemasOutput}export const routeResponseSchemas: Record<string, Record<string, { schema: z.ZodTypeAny; ref: string | null; hasFormData?: boolean }>> = {\n${routeSchemasOutput}\n};\n`;\n\n const file = Bun.file(outputPath);\n \n try {\n if (await file.exists()) {\n const existing = await file.text();\n if (existing === output) {\n console.log(`✅ Response schemas unchanged (${routes.length} routes)`);\n return;\n }\n }\n } catch {\n // Arquivo não existe\n }\n\n await Bun.write(outputPath, output);\n console.log(`✅ Generated response schemas for ${routes.length} routes (${namedSchemasEntries.length} named schemas)`);\n}\n","import path from 'path';\nimport { generateRegistry } from './generate-registry.js';\nimport { generateSwaggerTypes } from './generate-swagger-types.js';\nimport type { ZetiConfigInternal } from '../types/config.js';\n\nexport interface RunPrebuildOptions {\n projectRoot?: string;\n zetiConfig?: ZetiConfigInternal;\n controllersPath?: string;\n registryPath?: string;\n swaggerOutputPath?: string;\n prismaImport?: string;\n /** Forçar regeneração mesmo se não houver mudanças */\n force?: boolean;\n}\n\nconst CACHE_FILE = '.zeti/.prebuild-cache.json';\n\nasync function getFileHash(filePath: string): Promise<string> {\n try {\n const file = Bun.file(filePath);\n const stat = await file.stat();\n return `${stat.mtime}-${stat.size}`;\n } catch {\n return '';\n }\n}\n\nasync function loadCache(projectRoot: string): Promise<Map<string, string>> {\n const cachePath = path.join(projectRoot, CACHE_FILE);\n try {\n const file = Bun.file(cachePath);\n if (await file.exists()) {\n const data = await file.json();\n return new Map(Object.entries(data));\n }\n } catch {\n // Cache corrupto, ignora\n }\n return new Map();\n}\n\nasync function saveCache(projectRoot: string, cache: Map<string, string>): Promise<void> {\n const cachePath = path.join(projectRoot, CACHE_FILE);\n try {\n await Bun.write(cachePath, JSON.stringify(Object.fromEntries(cache)));\n } catch {\n // Falha ao salvar cache não é crítico\n }\n}\n\nasync function hasChanges(controllersPath: string, cache: Map<string, string>): Promise<{ changed: boolean; newCache: Map<string, string> }> {\n const newCache = new Map<string, string>();\n let changed = false;\n\n // Verifica se a pasta existe\n const dirFile = Bun.file(controllersPath);\n try {\n await dirFile.stat();\n } catch {\n return { changed: cache.size > 0, newCache };\n }\n\n // Lista todos os arquivos .ts recursivamente usando Bun.Glob\n const glob = new Bun.Glob('**/*.ts');\n const files: string[] = [];\n \n for await (const file of glob.scan({ cwd: controllersPath, absolute: true })) {\n const name = path.basename(file);\n if (name !== 'index.ts' && name !== 'registry.ts') {\n files.push(file);\n }\n }\n\n // Processa em paralelo\n await Promise.all(files.map(async (file) => {\n const hash = await getFileHash(file);\n newCache.set(file, hash);\n\n if (cache.get(file) !== hash) {\n changed = true;\n }\n }));\n\n // Verifica se algum arquivo foi removido\n for (const file of cache.keys()) {\n if (!newCache.has(file)) {\n changed = true;\n break;\n }\n }\n\n return { changed, newCache };\n}\n\nconst APP_FILE_CONTENT = `import { createAppProxy, getRedisClient, hasRedis } from 'zeti-framework-backend';\nimport type { PrismaClient } from '@prisma/client';\nimport type { Redis } from 'ioredis';\n\nexport const app = createAppProxy<PrismaClient, any>();\n\n/**\n * Cliente Redis singleton via Proxy.\n * Disponível após configuração em startZeti({ redis: {...} }).\n * \n * @example\n * import { app, redis } from '@zeti/app';\n * \n * await redis.set('key', 'value');\n * const value = await redis.get('key');\n */\nexport const redis: Redis = new Proxy({} as Redis, {\n get(_, prop) {\n if (!hasRedis()) {\n throw new Error('[Redis] Not configured. Add redis config to startZeti()');\n }\n const client = getRedisClient();\n const value = (client as any)[prop];\n return typeof value === 'function' ? value.bind(client) : value;\n }\n});\n\nexport const { get, post, put, del, patch, createMiddleware } = app;\n`;\n\nconst PRISMA_HELPERS_CONTENT = `/**\n * Helpers tipados para o PrismaClient do projeto\n * \n * Gerado automaticamente pelo zeti-framework-backend.\n * Use estes helpers em middlewares e outros lugares onde\n * o tipo do PrismaClient não é inferido automaticamente.\n */\n\nimport type { Context, Next } from 'hono';\nimport type { PrismaClient } from '@prisma/client';\nimport { \n getPrismaClient as _getPrismaClient, \n createMiddleware as _createMiddleware,\n} from 'zeti-framework-backend';\nimport type { MiddlewareHandler as _MiddlewareHandler } from 'zeti-framework-backend';\n\n// Re-exporta o tipo do PrismaClient\nexport type { PrismaClient };\nexport type AppPrismaClient = PrismaClient;\n\n/**\n * Handler de middleware tipado com o PrismaClient do projeto.\n */\nexport type MiddlewareHandler = _MiddlewareHandler<PrismaClient>;\n\n/**\n * Cria um middleware com o db tipado automaticamente.\n * \n * @example\n * import { createMiddleware } from '.zeti/prisma';\n * \n * export const authMiddleware = createMiddleware(async (c, next, db) => {\n * // db já vem tipado com os models do schema.prisma\n * const user = await db.user.findUnique({\n * where: { id: c.req.header('x-user-id') }\n * });\n * \n * if (!user) {\n * return c.json({ error: 'Unauthorized' }, 401);\n * }\n * \n * c.set('user', user);\n * await next();\n * });\n */\nexport function createMiddleware(\n handler: MiddlewareHandler\n): (c: Context, next: Next) => Promise<void | Response> {\n return _createMiddleware<PrismaClient>(handler);\n}\n\n/**\n * Cria uma factory de middleware com db tipado.\n * \n * @example\n * import { createMiddlewareFactory } from '.zeti/prisma';\n * \n * const requirePermission = createMiddlewareFactory(\n * (permissions: string[]) => async (c, next, db) => {\n * const user = c.get('user');\n * const userPerms = await db.permission.findMany({\n * where: { userId: user.id }\n * });\n * \n * if (!permissions.every(p => userPerms.some(up => up.name === p))) {\n * return c.json({ error: 'Forbidden' }, 403);\n * }\n * \n * await next();\n * }\n * );\n * \n * // Uso:\n * app.use('/admin/*', requirePermission(['admin:read']));\n */\nexport function createMiddlewareFactory<T extends any[]>(\n factory: (...args: T) => MiddlewareHandler\n): (...args: T) => (c: Context, next: Next) => Promise<void | Response> {\n return (...args: T) => _createMiddleware<PrismaClient>(factory(...args));\n}\n\n/**\n * Retorna o PrismaClient com tipagem correta do projeto\n * \n * @param tenantId - ID do tenant (opcional, usa o padrão se não fornecido)\n * @returns PrismaClient tipado com os models do schema.prisma\n * \n * @example\n * const db = getPrismaClient();\n * const users = await db.user.findMany(); // ✅ Tipado corretamente\n */\nexport function getPrismaClient(tenantId?: string): PrismaClient {\n return _getPrismaClient<PrismaClient>(tenantId);\n}\n`;\n\nasync function ensureAppFile(zetiDir: string, prismaImport: string): Promise<boolean> {\n const appPath = path.join(zetiDir, 'app.ts');\n const expectedContent = APP_FILE_CONTENT.replace('@prisma/client', prismaImport);\n \n try {\n const file = Bun.file(appPath);\n if (await file.exists()) {\n const currentContent = await file.text();\n if (currentContent === expectedContent) {\n return false; // Não mudou\n }\n }\n } catch {\n // Arquivo não existe ou erro ao ler\n }\n \n await Bun.write(appPath, expectedContent);\n return true;\n}\n\nasync function ensurePrismaHelpersFile(zetiDir: string, prismaImport: string): Promise<boolean> {\n const helpersPath = path.join(zetiDir, 'prisma.ts');\n const expectedContent = PRISMA_HELPERS_CONTENT.replace(/@prisma\\/client/g, prismaImport);\n \n try {\n const file = Bun.file(helpersPath);\n if (await file.exists()) {\n const currentContent = await file.text();\n if (currentContent === expectedContent) {\n return false; // Não mudou\n }\n }\n } catch {\n // Arquivo não existe ou erro ao ler\n }\n \n await Bun.write(helpersPath, expectedContent);\n return true;\n}\n\nexport async function runPrebuild(options: RunPrebuildOptions = {}): Promise<void> {\n const startTime = Bun.nanoseconds();\n const projectRoot = path.resolve(options.projectRoot || process.cwd());\n const zetiConfig = options.zetiConfig;\n\n const controllersPath = path.join(\n projectRoot,\n options.controllersPath || 'src/controllers'\n );\n const zetiDir = path.join(projectRoot, '.zeti');\n const registryPath = path.join(zetiDir, 'registry.ts');\n const swaggerOutputPath =\n options.swaggerOutputPath ||\n (zetiConfig?.swagger?.outputPath\n ? path.isAbsolute(zetiConfig.swagger.outputPath)\n ? zetiConfig.swagger.outputPath\n : path.join(projectRoot, zetiConfig.swagger.outputPath)\n : path.join(zetiDir, 'generated/swagger-schemas.ts'));\n\n // Garante que a pasta .zeti existe\n const fs = await import('fs');\n if (!fs.existsSync(zetiDir)) {\n fs.mkdirSync(zetiDir, { recursive: true });\n console.log('📁 [zeti] Created .zeti directory');\n }\n\n // Verifica se app.ts e prisma.ts precisam ser criados/atualizados\n const prismaImport = options.prismaImport || '@prisma/client';\n const [appChanged, prismaHelpersChanged] = await Promise.all([\n ensureAppFile(zetiDir, prismaImport),\n ensurePrismaHelpersFile(zetiDir, prismaImport),\n ]);\n\n // Carrega cache e verifica mudanças\n const cache = await loadCache(projectRoot);\n const { changed, newCache } = await hasChanges(controllersPath, cache);\n\n if (!options.force && !changed && !appChanged && !prismaHelpersChanged) {\n const elapsed = ((Bun.nanoseconds() - startTime) / 1_000_000).toFixed(0);\n console.log(`⚡ [zeti] No changes detected (${elapsed}ms)`);\n return;\n }\n\n console.log('🔄 [zeti] Generating files...');\n\n // Gera registry e swagger em paralelo\n await Promise.all([\n generateRegistry({\n controllersPath,\n indexPath: registryPath,\n outputMode: 'standalone',\n }),\n generateSwaggerTypes({\n controllersPath,\n outputPath: swaggerOutputPath,\n }),\n ]);\n\n // Salva cache\n await saveCache(projectRoot, newCache);\n\n const elapsed = ((Bun.nanoseconds() - startTime) / 1_000_000).toFixed(0);\n console.log(`✅ [zeti] Prebuild complete! (${elapsed}ms)`);\n}\n"],"mappings":"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","names":["file","path","path","path","path","elapsed"]}
|
|
@@ -290,6 +290,7 @@ async function generateSwagger(registry, config, options) {
|
|
|
290
290
|
for (const [name, schema] of Object.entries(namedSchemas)) {
|
|
291
291
|
componentsSchemas[name] = zodToJsonSchema(schema);
|
|
292
292
|
}
|
|
293
|
+
console.log("[Swagger Generator] Servers config:", config.servers);
|
|
293
294
|
return {
|
|
294
295
|
openapi: "3.0.3",
|
|
295
296
|
info: {
|
|
@@ -321,4 +322,4 @@ export {
|
|
|
321
322
|
isMultipleFileSchema,
|
|
322
323
|
generateSwagger
|
|
323
324
|
};
|
|
324
|
-
//# sourceMappingURL=chunk-
|
|
325
|
+
//# sourceMappingURL=chunk-O3LUZPTQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/swagger/zod-converter.ts","../src/utils/zod-file.ts","../src/swagger/generator.ts"],"sourcesContent":["import { z, ZodTypeAny, ZodObject, ZodString, ZodNumber, ZodBoolean, ZodArray, ZodOptional, ZodNullable, ZodEnum, ZodUnion, ZodEffects, ZodDefault, ZodLiteral, ZodDate } from 'zod';\n\n/**\n * Extrai o tipo base de um schema Zod, removendo wrappers como ZodEffects, ZodOptional, etc.\n */\nfunction unwrapZodType(schema: ZodTypeAny): ZodTypeAny {\n if (schema instanceof ZodEffects) {\n const innerSchema = schema._def.schema;\n if (innerSchema) {\n return unwrapZodType(innerSchema);\n }\n }\n if (schema instanceof ZodOptional) {\n return unwrapZodType(schema._def.innerType);\n }\n if (schema instanceof ZodNullable) {\n return unwrapZodType(schema._def.innerType);\n }\n if (schema instanceof ZodDefault) {\n return unwrapZodType(schema._def.innerType);\n }\n return schema;\n}\n\n/**\n * Verifica se um schema é opcional em algum nível da cadeia de wrappers.\n */\nfunction checkIsOptional(schema: ZodTypeAny): boolean {\n if (schema instanceof ZodOptional) {\n return true;\n }\n if (schema instanceof ZodDefault) {\n return true; // ZodDefault implica em opcional (tem valor padrão)\n }\n if (schema instanceof ZodEffects) {\n const innerSchema = schema._def.schema;\n if (innerSchema) {\n return checkIsOptional(innerSchema);\n }\n }\n return false;\n}\n\nexport function zodToJsonSchema(schema: ZodTypeAny): any {\n // ZodEffects (preprocess, refine, transform) - pega o tipo interno\n if (schema instanceof ZodEffects) {\n // O tipo interno está em schema._def.schema\n const innerSchema = schema._def.schema;\n if (innerSchema) {\n return zodToJsonSchema(innerSchema);\n }\n // Fallback: tenta detectar pelo typeName do inner\n return { type: 'string' };\n }\n \n // ZodDefault - pega o tipo interno\n if (schema instanceof ZodDefault) {\n return zodToJsonSchema(schema._def.innerType);\n }\n \n if (schema instanceof ZodString) {\n return { type: 'string' };\n }\n if (schema instanceof ZodNumber) {\n return { type: 'number' };\n }\n if (schema instanceof ZodBoolean) {\n return { type: 'boolean' };\n }\n if (schema instanceof ZodDate) {\n return { type: 'string', format: 'date-time' };\n }\n if (schema instanceof ZodLiteral) {\n const value = schema._def.value;\n const type = typeof value === 'number' ? 'number' : typeof value === 'boolean' ? 'boolean' : 'string';\n return { type, enum: [value] };\n }\n if (schema instanceof ZodArray) {\n return { type: 'array', items: zodToJsonSchema(schema._def.type) };\n }\n if (schema instanceof ZodOptional) {\n return zodToJsonSchema(schema._def.innerType);\n }\n if (schema instanceof ZodNullable) {\n return { ...zodToJsonSchema(schema._def.innerType), nullable: true };\n }\n if (schema instanceof ZodEnum) {\n return { type: 'string', enum: schema._def.values };\n }\n if (schema instanceof ZodUnion) {\n const options = schema._def.options.map((option: ZodTypeAny) => {\n return zodToJsonSchema(option);\n });\n return { oneOf: options };\n }\n if (schema instanceof ZodObject) {\n const shape = schema.shape;\n const properties: Record<string, any> = {};\n const required: string[] = [];\n\n for (const [key, value] of Object.entries(shape)) {\n properties[key] = zodToJsonSchema(value as ZodTypeAny);\n // Verifica se é opcional verificando se existe ZodOptional em algum nível\n const isOptional = checkIsOptional(value as ZodTypeAny);\n if (!isOptional) {\n required.push(key);\n }\n }\n\n return {\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n };\n }\n\n // Fallback: tenta detectar pelo _def.typeName\n const typeName = (schema as any)?._def?.typeName;\n if (typeName === 'ZodString') return { type: 'string' };\n if (typeName === 'ZodNumber') return { type: 'number' };\n if (typeName === 'ZodBoolean') return { type: 'boolean' };\n\n return { type: 'string' };\n}\n","import { z } from 'zod';\r\n\r\n/**\r\n * Symbol usado para identificar schemas de arquivo\r\n */\r\nexport const FILE_SCHEMA_SYMBOL = Symbol.for('zeti:file-schema');\r\n\r\n/**\r\n * Cria um schema Zod para upload de arquivo\r\n * \r\n * @example\r\n * ```typescript\r\n * app.post(\"/upload\", {\r\n * middleware: {\r\n * schema: (zod) => ({\r\n * formData: zod.object({\r\n * file: zFile(),\r\n * avatar: zFile(\"Foto de perfil\"),\r\n * documents: zFiles(\"Documentos PDF\"),\r\n * }),\r\n * }),\r\n * },\r\n * route: async ({ formData }) => {\r\n * const file = formData.file as File;\r\n * // ...\r\n * },\r\n * });\r\n * ```\r\n */\r\nexport function zFile(description?: string) {\r\n const schema = z.any().describe(description || 'File upload');\r\n // Marca o schema como arquivo usando metadata\r\n (schema as any)._def[FILE_SCHEMA_SYMBOL] = true;\r\n (schema as any)._def.isFile = true;\r\n return schema;\r\n}\r\n\r\n/**\r\n * Cria um schema Zod para upload de múltiplos arquivos\r\n */\r\nexport function zFiles(description?: string) {\r\n const schema = z.array(z.any()).describe(description || 'Multiple file upload');\r\n // Marca o schema como array de arquivos\r\n (schema as any)._def[FILE_SCHEMA_SYMBOL] = true;\r\n (schema as any)._def.isFile = true;\r\n (schema as any)._def.isMultiple = true;\r\n return schema;\r\n}\r\n\r\n/**\r\n * Verifica se um schema Zod é um schema de arquivo\r\n */\r\nexport function isFileSchema(schema: z.ZodTypeAny): boolean {\r\n return (schema as any)?._def?.[FILE_SCHEMA_SYMBOL] === true || \r\n (schema as any)?._def?.isFile === true;\r\n}\r\n\r\n/**\r\n * Verifica se um schema Zod é um schema de múltiplos arquivos\r\n */\r\nexport function isMultipleFileSchema(schema: z.ZodTypeAny): boolean {\r\n return isFileSchema(schema) && (schema as any)?._def?.isMultiple === true;\r\n}\r\n","import type { SwaggerRegistry } from './registry';\r\nimport type { ZetiSwaggerConfig } from '../types/config';\r\nimport { zodToJsonSchema } from './zod-converter';\r\nimport type { RouteMetadata } from '../types/framework';\r\nimport type { ZodTypeAny, ZodObject } from 'zod';\r\nimport { isFileSchema, isMultipleFileSchema } from '../utils/zod-file';\r\n\r\nfunction extractPathParams(path: string): string[] {\r\n const matches = path.match(/:([^/]+)/g);\r\n return matches ? matches.map((m) => m.slice(1)) : [];\r\n}\r\n\r\nfunction pathToOpenAPI(path: string): string {\r\n return path.replace(/:([^/]+)/g, '{$1}');\r\n}\r\n\r\nfunction extractTag(path: string): string {\r\n const parts = path.split('/').filter(Boolean);\r\n return parts[0] || 'default';\r\n}\r\n\r\nexport interface SwaggerGeneratorOptions {\r\n loadGeneratedSchemas?: () => Promise<{\r\n routeResponseSchemas?: Record<string, Record<string, { schema: ZodTypeAny; ref: string | null }>>;\r\n namedSchemas?: Record<string, ZodTypeAny>;\r\n }>;\r\n}\r\n\r\nexport async function generateSwagger(\r\n registry: SwaggerRegistry,\r\n config: ZetiSwaggerConfig,\r\n options?: SwaggerGeneratorOptions\r\n): Promise<object> {\r\n const routes = registry.getAll();\r\n const paths: Record<string, any> = {};\r\n \r\n // Try to load generated schemas\r\n let routeResponseSchemas: Record<string, Record<string, { schema: ZodTypeAny; ref: string | null }>> = {};\r\n let namedSchemas: Record<string, ZodTypeAny> = {};\r\n \r\n if (options?.loadGeneratedSchemas) {\r\n try {\r\n const schemas = await options.loadGeneratedSchemas();\r\n if (schemas.routeResponseSchemas) {\r\n routeResponseSchemas = schemas.routeResponseSchemas;\r\n }\r\n if (schemas.namedSchemas) {\r\n namedSchemas = schemas.namedSchemas;\r\n }\r\n } catch {\r\n // File doesn't exist yet (first build) - ignore\r\n }\r\n }\r\n\r\n for (const route of routes) {\r\n const openApiPath = pathToOpenAPI(route.path);\r\n const pathParams = extractPathParams(route.path);\r\n const tag = route.tags?.[0] || extractTag(route.path);\r\n\r\n if (!paths[openApiPath]) {\r\n paths[openApiPath] = {};\r\n }\r\n\r\n // Try to get response schema: 1) from generated types, 2) from manual schema, 3) fallback\r\n const generated = routeResponseSchemas[route.path]?.[route.method];\r\n let responseJsonSchema: any;\r\n \r\n if (generated?.ref) {\r\n // Use $ref to reference named schema\r\n responseJsonSchema = { $ref: `#/components/schemas/${generated.ref}` };\r\n } else if (generated?.schema) {\r\n responseJsonSchema = zodToJsonSchema(generated.schema);\r\n } else if (route.responseSchema) {\r\n responseJsonSchema = zodToJsonSchema(route.responseSchema);\r\n } else {\r\n responseJsonSchema = { type: 'object' };\r\n }\r\n\r\n const operation: any = {\r\n tags: route.tags || [tag],\r\n summary: route.summary || `${route.method.toUpperCase()} ${route.path}`,\r\n description: route.description,\r\n parameters: [],\r\n responses: {\r\n '200': {\r\n description: 'Successful response',\r\n content: {\r\n 'application/json': {\r\n schema: responseJsonSchema,\r\n },\r\n },\r\n },\r\n },\r\n };\r\n\r\n // Adiciona headers globais configurados\r\n if (config.globalHeaders?.length) {\r\n for (const header of config.globalHeaders) {\r\n operation.parameters.push({\r\n name: header.name,\r\n in: 'header',\r\n required: header.required ?? false,\r\n schema: { type: 'string' },\r\n description: header.description || `Header ${header.name}`,\r\n ...(header.example ? { example: header.example } : {}),\r\n });\r\n }\r\n }\r\n\r\n for (const param of pathParams) {\r\n operation.parameters.push({\r\n name: param,\r\n in: 'path',\r\n required: true,\r\n schema: { type: 'string' },\r\n });\r\n }\r\n\r\n if (route.querySchema) {\r\n const queryJsonSchema = zodToJsonSchema(route.querySchema);\r\n if (queryJsonSchema.properties) {\r\n for (const [name, schema] of Object.entries(queryJsonSchema.properties)) {\r\n operation.parameters.push({\r\n name,\r\n in: 'query',\r\n required: queryJsonSchema.required?.includes(name) || false,\r\n schema,\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (route.formDataSchema && ['post', 'put', 'patch'].includes(route.method)) {\r\n const formDataJsonSchema = zodToJsonSchema(route.formDataSchema);\r\n \r\n // Detecta campos de arquivo e ajusta o schema para OpenAPI\r\n const properties: Record<string, any> = { ...(formDataJsonSchema.properties || {}) };\r\n const required: string[] = formDataJsonSchema.required || [];\r\n \r\n // Verifica cada campo do schema original para detectar arquivos\r\n const originalSchema = route.formDataSchema as ZodObject<any>;\r\n if (originalSchema && typeof originalSchema === 'object' && 'shape' in originalSchema) {\r\n const shape = (originalSchema as any).shape || {};\r\n \r\n for (const [key, fieldSchema] of Object.entries(shape)) {\r\n const zodField = fieldSchema as ZodTypeAny;\r\n \r\n // Verifica se é um schema de arquivo usando nosso helper\r\n if (isFileSchema(zodField)) {\r\n const isMultiple = isMultipleFileSchema(zodField);\r\n const description = zodField.description || 'File upload';\r\n \r\n if (isMultiple) {\r\n properties[key] = {\r\n type: 'array',\r\n items: {\r\n type: 'string',\r\n format: 'binary',\r\n },\r\n description,\r\n };\r\n } else {\r\n properties[key] = {\r\n type: 'string',\r\n format: 'binary',\r\n description,\r\n };\r\n }\r\n }\r\n }\r\n }\r\n \r\n // Fallback: detecta por descrição ou tipo\r\n for (const [key, prop] of Object.entries(properties)) {\r\n const propObj = prop as any;\r\n // Se ainda não foi convertido e tem descrição indicando arquivo\r\n if (propObj.format !== 'binary') {\r\n if (propObj.description?.toLowerCase().includes('file') || \r\n propObj.description?.toLowerCase().includes('arquivo') ||\r\n propObj.description?.toLowerCase().includes('upload')) {\r\n properties[key] = {\r\n type: 'string',\r\n format: 'binary',\r\n description: propObj.description || 'File upload',\r\n };\r\n }\r\n }\r\n }\r\n \r\n operation.requestBody = {\r\n required: true,\r\n content: {\r\n 'multipart/form-data': {\r\n schema: {\r\n type: 'object',\r\n properties,\r\n ...(required.length > 0 ? { required } : {}),\r\n },\r\n },\r\n },\r\n };\r\n } else if (route.bodySchema && ['post', 'put', 'patch'].includes(route.method)) {\r\n const bodySchema = zodToJsonSchema(route.bodySchema);\r\n operation.requestBody = {\r\n required: true,\r\n content: {\r\n 'application/json': {\r\n schema: bodySchema,\r\n },\r\n },\r\n };\r\n }\r\n\r\n if (route.auth) {\r\n operation.security = [{ bearerAuth: [] }];\r\n operation.responses['401'] = { description: 'Unauthorized' };\r\n }\r\n\r\n if (route.claims?.length) {\r\n operation.responses['403'] = {\r\n description: `Forbidden - requires claims: ${route.claims.join(', ')}`,\r\n };\r\n }\r\n\r\n if (route.roles?.length) {\r\n operation.responses['403'] = {\r\n description: `Forbidden - requires roles: ${route.roles.join(', ')}`,\r\n };\r\n }\r\n\r\n paths[openApiPath][route.method] = operation;\r\n }\r\n\r\n // Build components.schemas from namedSchemas\r\n const componentsSchemas: Record<string, any> = {};\r\n for (const [name, schema] of Object.entries(namedSchemas)) {\r\n componentsSchemas[name] = zodToJsonSchema(schema);\r\n }\r\n\r\n return {\r\n openapi: '3.0.3',\r\n info: {\r\n title: config.title,\r\n version: config.version,\r\n description: 'Auto-generated API documentation',\r\n },\r\n servers: config.servers,\r\n paths,\r\n components: {\r\n ...(Object.keys(componentsSchemas).length > 0 ? { schemas: componentsSchemas } : {}),\r\n securitySchemes: {\r\n bearerAuth: {\r\n type: 'http',\r\n scheme: 'bearer',\r\n bearerFormat: 'JWT',\r\n },\r\n },\r\n },\r\n };\r\n}\r\n"],"mappings":"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","names":["z"]}
|
|
1
|
+
{"version":3,"sources":["../src/swagger/zod-converter.ts","../src/utils/zod-file.ts","../src/swagger/generator.ts"],"sourcesContent":["import { z, ZodTypeAny, ZodObject, ZodString, ZodNumber, ZodBoolean, ZodArray, ZodOptional, ZodNullable, ZodEnum, ZodUnion, ZodEffects, ZodDefault, ZodLiteral, ZodDate } from 'zod';\n\n/**\n * Extrai o tipo base de um schema Zod, removendo wrappers como ZodEffects, ZodOptional, etc.\n */\nfunction unwrapZodType(schema: ZodTypeAny): ZodTypeAny {\n if (schema instanceof ZodEffects) {\n const innerSchema = schema._def.schema;\n if (innerSchema) {\n return unwrapZodType(innerSchema);\n }\n }\n if (schema instanceof ZodOptional) {\n return unwrapZodType(schema._def.innerType);\n }\n if (schema instanceof ZodNullable) {\n return unwrapZodType(schema._def.innerType);\n }\n if (schema instanceof ZodDefault) {\n return unwrapZodType(schema._def.innerType);\n }\n return schema;\n}\n\n/**\n * Verifica se um schema é opcional em algum nível da cadeia de wrappers.\n */\nfunction checkIsOptional(schema: ZodTypeAny): boolean {\n if (schema instanceof ZodOptional) {\n return true;\n }\n if (schema instanceof ZodDefault) {\n return true; // ZodDefault implica em opcional (tem valor padrão)\n }\n if (schema instanceof ZodEffects) {\n const innerSchema = schema._def.schema;\n if (innerSchema) {\n return checkIsOptional(innerSchema);\n }\n }\n return false;\n}\n\nexport function zodToJsonSchema(schema: ZodTypeAny): any {\n // ZodEffects (preprocess, refine, transform) - pega o tipo interno\n if (schema instanceof ZodEffects) {\n // O tipo interno está em schema._def.schema\n const innerSchema = schema._def.schema;\n if (innerSchema) {\n return zodToJsonSchema(innerSchema);\n }\n // Fallback: tenta detectar pelo typeName do inner\n return { type: 'string' };\n }\n \n // ZodDefault - pega o tipo interno\n if (schema instanceof ZodDefault) {\n return zodToJsonSchema(schema._def.innerType);\n }\n \n if (schema instanceof ZodString) {\n return { type: 'string' };\n }\n if (schema instanceof ZodNumber) {\n return { type: 'number' };\n }\n if (schema instanceof ZodBoolean) {\n return { type: 'boolean' };\n }\n if (schema instanceof ZodDate) {\n return { type: 'string', format: 'date-time' };\n }\n if (schema instanceof ZodLiteral) {\n const value = schema._def.value;\n const type = typeof value === 'number' ? 'number' : typeof value === 'boolean' ? 'boolean' : 'string';\n return { type, enum: [value] };\n }\n if (schema instanceof ZodArray) {\n return { type: 'array', items: zodToJsonSchema(schema._def.type) };\n }\n if (schema instanceof ZodOptional) {\n return zodToJsonSchema(schema._def.innerType);\n }\n if (schema instanceof ZodNullable) {\n return { ...zodToJsonSchema(schema._def.innerType), nullable: true };\n }\n if (schema instanceof ZodEnum) {\n return { type: 'string', enum: schema._def.values };\n }\n if (schema instanceof ZodUnion) {\n const options = schema._def.options.map((option: ZodTypeAny) => {\n return zodToJsonSchema(option);\n });\n return { oneOf: options };\n }\n if (schema instanceof ZodObject) {\n const shape = schema.shape;\n const properties: Record<string, any> = {};\n const required: string[] = [];\n\n for (const [key, value] of Object.entries(shape)) {\n properties[key] = zodToJsonSchema(value as ZodTypeAny);\n // Verifica se é opcional verificando se existe ZodOptional em algum nível\n const isOptional = checkIsOptional(value as ZodTypeAny);\n if (!isOptional) {\n required.push(key);\n }\n }\n\n return {\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n };\n }\n\n // Fallback: tenta detectar pelo _def.typeName\n const typeName = (schema as any)?._def?.typeName;\n if (typeName === 'ZodString') return { type: 'string' };\n if (typeName === 'ZodNumber') return { type: 'number' };\n if (typeName === 'ZodBoolean') return { type: 'boolean' };\n\n return { type: 'string' };\n}\n","import { z } from 'zod';\r\n\r\n/**\r\n * Symbol usado para identificar schemas de arquivo\r\n */\r\nexport const FILE_SCHEMA_SYMBOL = Symbol.for('zeti:file-schema');\r\n\r\n/**\r\n * Cria um schema Zod para upload de arquivo\r\n * \r\n * @example\r\n * ```typescript\r\n * app.post(\"/upload\", {\r\n * middleware: {\r\n * schema: (zod) => ({\r\n * formData: zod.object({\r\n * file: zFile(),\r\n * avatar: zFile(\"Foto de perfil\"),\r\n * documents: zFiles(\"Documentos PDF\"),\r\n * }),\r\n * }),\r\n * },\r\n * route: async ({ formData }) => {\r\n * const file = formData.file as File;\r\n * // ...\r\n * },\r\n * });\r\n * ```\r\n */\r\nexport function zFile(description?: string) {\r\n const schema = z.any().describe(description || 'File upload');\r\n // Marca o schema como arquivo usando metadata\r\n (schema as any)._def[FILE_SCHEMA_SYMBOL] = true;\r\n (schema as any)._def.isFile = true;\r\n return schema;\r\n}\r\n\r\n/**\r\n * Cria um schema Zod para upload de múltiplos arquivos\r\n */\r\nexport function zFiles(description?: string) {\r\n const schema = z.array(z.any()).describe(description || 'Multiple file upload');\r\n // Marca o schema como array de arquivos\r\n (schema as any)._def[FILE_SCHEMA_SYMBOL] = true;\r\n (schema as any)._def.isFile = true;\r\n (schema as any)._def.isMultiple = true;\r\n return schema;\r\n}\r\n\r\n/**\r\n * Verifica se um schema Zod é um schema de arquivo\r\n */\r\nexport function isFileSchema(schema: z.ZodTypeAny): boolean {\r\n return (schema as any)?._def?.[FILE_SCHEMA_SYMBOL] === true || \r\n (schema as any)?._def?.isFile === true;\r\n}\r\n\r\n/**\r\n * Verifica se um schema Zod é um schema de múltiplos arquivos\r\n */\r\nexport function isMultipleFileSchema(schema: z.ZodTypeAny): boolean {\r\n return isFileSchema(schema) && (schema as any)?._def?.isMultiple === true;\r\n}\r\n","import type { SwaggerRegistry } from './registry';\r\nimport type { ZetiSwaggerConfig } from '../types/config';\r\nimport { zodToJsonSchema } from './zod-converter';\r\nimport type { RouteMetadata } from '../types/framework';\r\nimport type { ZodTypeAny, ZodObject } from 'zod';\r\nimport { isFileSchema, isMultipleFileSchema } from '../utils/zod-file';\r\n\r\nfunction extractPathParams(path: string): string[] {\r\n const matches = path.match(/:([^/]+)/g);\r\n return matches ? matches.map((m) => m.slice(1)) : [];\r\n}\r\n\r\nfunction pathToOpenAPI(path: string): string {\r\n return path.replace(/:([^/]+)/g, '{$1}');\r\n}\r\n\r\nfunction extractTag(path: string): string {\r\n const parts = path.split('/').filter(Boolean);\r\n return parts[0] || 'default';\r\n}\r\n\r\nexport interface SwaggerGeneratorOptions {\r\n loadGeneratedSchemas?: () => Promise<{\r\n routeResponseSchemas?: Record<string, Record<string, { schema: ZodTypeAny; ref: string | null }>>;\r\n namedSchemas?: Record<string, ZodTypeAny>;\r\n }>;\r\n}\r\n\r\nexport async function generateSwagger(\r\n registry: SwaggerRegistry,\r\n config: ZetiSwaggerConfig,\r\n options?: SwaggerGeneratorOptions\r\n): Promise<object> {\r\n const routes = registry.getAll();\r\n const paths: Record<string, any> = {};\r\n \r\n // Try to load generated schemas\r\n let routeResponseSchemas: Record<string, Record<string, { schema: ZodTypeAny; ref: string | null }>> = {};\r\n let namedSchemas: Record<string, ZodTypeAny> = {};\r\n \r\n if (options?.loadGeneratedSchemas) {\r\n try {\r\n const schemas = await options.loadGeneratedSchemas();\r\n if (schemas.routeResponseSchemas) {\r\n routeResponseSchemas = schemas.routeResponseSchemas;\r\n }\r\n if (schemas.namedSchemas) {\r\n namedSchemas = schemas.namedSchemas;\r\n }\r\n } catch {\r\n // File doesn't exist yet (first build) - ignore\r\n }\r\n }\r\n\r\n for (const route of routes) {\r\n const openApiPath = pathToOpenAPI(route.path);\r\n const pathParams = extractPathParams(route.path);\r\n const tag = route.tags?.[0] || extractTag(route.path);\r\n\r\n if (!paths[openApiPath]) {\r\n paths[openApiPath] = {};\r\n }\r\n\r\n // Try to get response schema: 1) from generated types, 2) from manual schema, 3) fallback\r\n const generated = routeResponseSchemas[route.path]?.[route.method];\r\n let responseJsonSchema: any;\r\n \r\n if (generated?.ref) {\r\n // Use $ref to reference named schema\r\n responseJsonSchema = { $ref: `#/components/schemas/${generated.ref}` };\r\n } else if (generated?.schema) {\r\n responseJsonSchema = zodToJsonSchema(generated.schema);\r\n } else if (route.responseSchema) {\r\n responseJsonSchema = zodToJsonSchema(route.responseSchema);\r\n } else {\r\n responseJsonSchema = { type: 'object' };\r\n }\r\n\r\n const operation: any = {\r\n tags: route.tags || [tag],\r\n summary: route.summary || `${route.method.toUpperCase()} ${route.path}`,\r\n description: route.description,\r\n parameters: [],\r\n responses: {\r\n '200': {\r\n description: 'Successful response',\r\n content: {\r\n 'application/json': {\r\n schema: responseJsonSchema,\r\n },\r\n },\r\n },\r\n },\r\n };\r\n\r\n // Adiciona headers globais configurados\r\n if (config.globalHeaders?.length) {\r\n for (const header of config.globalHeaders) {\r\n operation.parameters.push({\r\n name: header.name,\r\n in: 'header',\r\n required: header.required ?? false,\r\n schema: { type: 'string' },\r\n description: header.description || `Header ${header.name}`,\r\n ...(header.example ? { example: header.example } : {}),\r\n });\r\n }\r\n }\r\n\r\n for (const param of pathParams) {\r\n operation.parameters.push({\r\n name: param,\r\n in: 'path',\r\n required: true,\r\n schema: { type: 'string' },\r\n });\r\n }\r\n\r\n if (route.querySchema) {\r\n const queryJsonSchema = zodToJsonSchema(route.querySchema);\r\n if (queryJsonSchema.properties) {\r\n for (const [name, schema] of Object.entries(queryJsonSchema.properties)) {\r\n operation.parameters.push({\r\n name,\r\n in: 'query',\r\n required: queryJsonSchema.required?.includes(name) || false,\r\n schema,\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (route.formDataSchema && ['post', 'put', 'patch'].includes(route.method)) {\r\n const formDataJsonSchema = zodToJsonSchema(route.formDataSchema);\r\n \r\n // Detecta campos de arquivo e ajusta o schema para OpenAPI\r\n const properties: Record<string, any> = { ...(formDataJsonSchema.properties || {}) };\r\n const required: string[] = formDataJsonSchema.required || [];\r\n \r\n // Verifica cada campo do schema original para detectar arquivos\r\n const originalSchema = route.formDataSchema as ZodObject<any>;\r\n if (originalSchema && typeof originalSchema === 'object' && 'shape' in originalSchema) {\r\n const shape = (originalSchema as any).shape || {};\r\n \r\n for (const [key, fieldSchema] of Object.entries(shape)) {\r\n const zodField = fieldSchema as ZodTypeAny;\r\n \r\n // Verifica se é um schema de arquivo usando nosso helper\r\n if (isFileSchema(zodField)) {\r\n const isMultiple = isMultipleFileSchema(zodField);\r\n const description = zodField.description || 'File upload';\r\n \r\n if (isMultiple) {\r\n properties[key] = {\r\n type: 'array',\r\n items: {\r\n type: 'string',\r\n format: 'binary',\r\n },\r\n description,\r\n };\r\n } else {\r\n properties[key] = {\r\n type: 'string',\r\n format: 'binary',\r\n description,\r\n };\r\n }\r\n }\r\n }\r\n }\r\n \r\n // Fallback: detecta por descrição ou tipo\r\n for (const [key, prop] of Object.entries(properties)) {\r\n const propObj = prop as any;\r\n // Se ainda não foi convertido e tem descrição indicando arquivo\r\n if (propObj.format !== 'binary') {\r\n if (propObj.description?.toLowerCase().includes('file') || \r\n propObj.description?.toLowerCase().includes('arquivo') ||\r\n propObj.description?.toLowerCase().includes('upload')) {\r\n properties[key] = {\r\n type: 'string',\r\n format: 'binary',\r\n description: propObj.description || 'File upload',\r\n };\r\n }\r\n }\r\n }\r\n \r\n operation.requestBody = {\r\n required: true,\r\n content: {\r\n 'multipart/form-data': {\r\n schema: {\r\n type: 'object',\r\n properties,\r\n ...(required.length > 0 ? { required } : {}),\r\n },\r\n },\r\n },\r\n };\r\n } else if (route.bodySchema && ['post', 'put', 'patch'].includes(route.method)) {\r\n const bodySchema = zodToJsonSchema(route.bodySchema);\r\n operation.requestBody = {\r\n required: true,\r\n content: {\r\n 'application/json': {\r\n schema: bodySchema,\r\n },\r\n },\r\n };\r\n }\r\n\r\n if (route.auth) {\r\n operation.security = [{ bearerAuth: [] }];\r\n operation.responses['401'] = { description: 'Unauthorized' };\r\n }\r\n\r\n if (route.claims?.length) {\r\n operation.responses['403'] = {\r\n description: `Forbidden - requires claims: ${route.claims.join(', ')}`,\r\n };\r\n }\r\n\r\n if (route.roles?.length) {\r\n operation.responses['403'] = {\r\n description: `Forbidden - requires roles: ${route.roles.join(', ')}`,\r\n };\r\n }\r\n\r\n paths[openApiPath][route.method] = operation;\r\n }\r\n\r\n // Build components.schemas from namedSchemas\r\n const componentsSchemas: Record<string, any> = {};\r\n for (const [name, schema] of Object.entries(namedSchemas)) {\r\n componentsSchemas[name] = zodToJsonSchema(schema);\r\n }\r\n\r\n console.log('[Swagger Generator] Servers config:', config.servers);\r\n \r\n return {\r\n openapi: '3.0.3',\r\n info: {\r\n title: config.title,\r\n version: config.version,\r\n description: 'Auto-generated API documentation',\r\n },\r\n servers: config.servers,\r\n paths,\r\n components: {\r\n ...(Object.keys(componentsSchemas).length > 0 ? { schemas: componentsSchemas } : {}),\r\n securitySchemes: {\r\n bearerAuth: {\r\n type: 'http',\r\n scheme: 'bearer',\r\n bearerFormat: 'JWT',\r\n },\r\n },\r\n },\r\n };\r\n}\r\n"],"mappings":"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","names":["z"]}
|
package/dist/cli/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
generateRegistry,
|
|
10
10
|
generateSwaggerTypes,
|
|
11
11
|
runPrebuild
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-MXFWPHXO.js";
|
|
13
13
|
import {
|
|
14
14
|
definePrismaConfig,
|
|
15
15
|
getAllDatabaseUrls
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
isMultipleFileSchema,
|
|
26
26
|
zFile,
|
|
27
27
|
zFiles
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-O3LUZPTQ.js";
|
|
29
29
|
import {
|
|
30
30
|
__commonJS,
|
|
31
31
|
__require,
|
|
@@ -10239,7 +10239,7 @@ function createZetiApp(options) {
|
|
|
10239
10239
|
let cachedSchemas = null;
|
|
10240
10240
|
honoApp.get(uiPath, swaggerUI({ url: docPath }));
|
|
10241
10241
|
honoApp.get(docPath, async (c) => {
|
|
10242
|
-
const { generateSwagger: generateSwagger2 } = await import("./generator-
|
|
10242
|
+
const { generateSwagger: generateSwagger2 } = await import("./generator-4OQC53GR.js");
|
|
10243
10243
|
const loadGeneratedSchemas = async () => {
|
|
10244
10244
|
if (cachedSchemas) {
|
|
10245
10245
|
return cachedSchemas;
|
package/dist/scripts/index.js
CHANGED
package/dist/swagger/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/scripts/generate-registry.ts","../src/scripts/generate-swagger-types.ts","../src/scripts/run-prebuild.ts"],"sourcesContent":["import path from 'path';\n\nexport interface GenerateRegistryOptions {\n controllersPath: string;\n indexPath: string;\n startMarker?: string;\n endMarker?: string;\n /** Se true, escreve apenas os imports no arquivo (para .zeti/registry.ts) */\n outputMode?: 'inject' | 'standalone';\n}\n\nexport async function generateRegistry(options: GenerateRegistryOptions) {\n const {\n controllersPath,\n indexPath,\n startMarker = '// @CONTROLLERS_START',\n endMarker = '// @CONTROLLERS_END',\n outputMode = 'inject',\n } = options;\n\n // Usa Bun.Glob para listar arquivos (mais rápido)\n const glob = new Bun.Glob('**/*.ts');\n const imports: string[] = [];\n\n for await (const file of glob.scan({ cwd: controllersPath, absolute: true })) {\n const name = path.basename(file);\n if (name === 'index.ts' || name === 'registry.ts') continue;\n\n const relativePath = path.relative(path.dirname(indexPath), file);\n const importPath = relativePath.replace(/\\\\/g, '/').replace(/\\.ts$/, '');\n imports.push(`import \"${importPath.startsWith('.') ? importPath : './' + importPath}\";`);\n }\n\n if (outputMode === 'standalone') {\n const content = `// Generated by zeti-framework-backend. Do not edit.\n\n${imports.join('\\n')}\n`;\n\n // Só escreve se o conteúdo mudou\n const file = Bun.file(indexPath);\n try {\n if (await file.exists()) {\n const existing = await file.text();\n if (existing === content) {\n console.log(`✅ Registry unchanged (${imports.length} controllers)`);\n return;\n }\n }\n } catch {\n // Arquivo não existe\n }\n\n await Bun.write(indexPath, content);\n console.log(`✅ Generated .zeti/registry.ts with ${imports.length} controller imports`);\n return;\n }\n\n // Modo inject\n const file = Bun.file(indexPath);\n const indexContent = await file.exists() ? await file.text() : '';\n\n const generatedBlock = `${startMarker}\\n${imports.join('\\n')}\\n${endMarker}`;\n\n let newContent: string;\n if (indexContent.includes(startMarker)) {\n const regex = new RegExp(`${startMarker}[\\\\s\\\\S]*?${endMarker}`, 'g');\n newContent = indexContent.replace(regex, generatedBlock);\n } else {\n newContent = indexContent + (indexContent ? '\\n\\n' : '') + generatedBlock;\n }\n\n // Só escreve se o conteúdo mudou\n if (newContent !== indexContent) {\n await Bun.write(indexPath, newContent);\n console.log(`✅ Injected ${imports.length} controller imports into ${indexPath}`);\n } else {\n console.log(`✅ Registry unchanged (${imports.length} controllers)`);\n }\n}\n","import path from 'path';\n\nexport interface GenerateSwaggerTypesOptions {\n controllersPath: string;\n outputPath: string;\n}\n\ninterface RouteInfo {\n path: string;\n method: string;\n returnType: string;\n schemaName?: string;\n hasFormData?: boolean;\n}\n\n// Divide um union type corretamente, respeitando aninhamento\nfunction splitUnionType(typeStr: string): string[] {\n const parts: string[] = [];\n let depth = 0;\n let current = '';\n \n for (let i = 0; i < typeStr.length; i++) {\n const char = typeStr[i];\n if (char === '<' || char === '{' || char === '[' || char === '(') depth++;\n else if (char === '>' || char === '}' || char === ']' || char === ')') depth--;\n else if (char === '|' && depth === 0) {\n if (current.trim()) parts.push(current.trim());\n current = '';\n continue;\n }\n current += char;\n }\n if (current.trim()) parts.push(current.trim());\n \n return parts;\n}\n\n// Converte tipo TypeScript para Zod schema, usando referências para tipos nomeados\nfunction typeToZodSchemaWithRefs(\n typeStr: string, \n typeDefinitions: Map<string, string>, \n namedSchemas: Map<string, string>,\n depth = 0\n): string {\n if (depth > 10) return 'z.any()';\n \n typeStr = typeStr.trim();\n \n // Remove Promise wrapper\n const promiseMatch = typeStr.match(/^Promise<(.+)>$/);\n if (promiseMatch) {\n typeStr = promiseMatch[1].trim();\n }\n \n // Tipos primitivos\n if (typeStr === 'string') return 'z.string()';\n if (typeStr === 'number') return 'z.number()';\n if (typeStr === 'boolean') return 'z.boolean()';\n if (typeStr === 'null') return 'z.null()';\n if (typeStr === 'undefined') return 'z.undefined()';\n if (typeStr === 'any') return 'z.any()';\n if (typeStr === 'unknown') return 'z.unknown()';\n if (typeStr === 'void') return 'z.void()';\n if (typeStr === 'Date') return 'z.date()';\n \n // String literal\n const stringLiteralMatch = typeStr.match(/^[\"'](.+)[\"']$/);\n if (stringLiteralMatch) {\n return `z.literal(\"${stringLiteralMatch[1]}\")`;\n }\n \n // Number literal\n if (/^\\d+$/.test(typeStr)) {\n return `z.literal(${typeStr})`;\n }\n \n // Array com tipo nomeado: TypeName[]\n const arrayNamedMatch = typeStr.match(/^(\\w+)\\[\\]$/);\n if (arrayNamedMatch) {\n const itemType = arrayNamedMatch[1];\n if (typeDefinitions.has(itemType)) {\n // Garante que o tipo referenciado seja processado\n if (!namedSchemas.has(itemType)) {\n const typeDef = typeDefinitions.get(itemType)!;\n namedSchemas.set(itemType, typeToZodSchemaWithRefs(typeDef, typeDefinitions, namedSchemas, depth + 1));\n }\n return `z.array(namedSchemas.${itemType})`;\n }\n return `z.array(${typeToZodSchemaWithRefs(itemType, typeDefinitions, namedSchemas, depth + 1)})`;\n }\n \n // Array genérico: Array<Type>\n const arrayGenericMatch = typeStr.match(/^Array<(.+)>$/);\n if (arrayGenericMatch) {\n const itemType = arrayGenericMatch[1].trim();\n if (typeDefinitions.has(itemType)) {\n if (!namedSchemas.has(itemType)) {\n const typeDef = typeDefinitions.get(itemType)!;\n namedSchemas.set(itemType, typeToZodSchemaWithRefs(typeDef, typeDefinitions, namedSchemas, depth + 1));\n }\n return `z.array(namedSchemas.${itemType})`;\n }\n return `z.array(${typeToZodSchemaWithRefs(itemType, typeDefinitions, namedSchemas, depth + 1)})`;\n }\n \n // Verifica se é uma referência a um tipo definido\n if (/^[A-Z]\\w*$/.test(typeStr) && typeDefinitions.has(typeStr)) {\n // Garante que o tipo referenciado seja processado\n if (!namedSchemas.has(typeStr)) {\n const typeDef = typeDefinitions.get(typeStr)!;\n namedSchemas.set(typeStr, typeToZodSchemaWithRefs(typeDef, typeDefinitions, namedSchemas, depth + 1));\n }\n return `namedSchemas.${typeStr}`;\n }\n \n // Object inline { key: type, ... }\n if (typeStr.startsWith('{') && typeStr.endsWith('}')) {\n const inner = typeStr.slice(1, -1).trim();\n if (!inner) return 'z.object({})';\n \n const props: string[] = [];\n let currentDepth = 0;\n let current = '';\n let inString = false;\n let stringChar = '';\n \n for (let i = 0; i < inner.length; i++) {\n const char = inner[i];\n \n if (!inString && (char === '\"' || char === \"'\" || char === '`')) {\n inString = true;\n stringChar = char;\n current += char;\n } else if (inString && char === stringChar && inner[i - 1] !== '\\\\') {\n inString = false;\n current += char;\n } else if (!inString) {\n if (char === '{' || char === '<' || char === '[' || char === '(') currentDepth++;\n else if (char === '}' || char === '>' || char === ']' || char === ')') currentDepth--;\n \n if ((char === ',' || char === ';') && currentDepth === 0) {\n if (current.trim()) props.push(current.trim());\n current = '';\n } else {\n current += char;\n }\n } else {\n current += char;\n }\n }\n if (current.trim()) props.push(current.trim());\n \n const zodProps = props.map(prop => {\n let colonIndex = -1;\n let propDepth = 0;\n for (let i = 0; i < prop.length; i++) {\n const char = prop[i];\n if (char === '<' || char === '{' || char === '[') propDepth++;\n else if (char === '>' || char === '}' || char === ']') propDepth--;\n else if (char === ':' && propDepth === 0) {\n colonIndex = i;\n break;\n }\n }\n \n if (colonIndex === -1) return null;\n \n let key = prop.slice(0, colonIndex).trim();\n const value = prop.slice(colonIndex + 1).trim();\n \n const isOptional = key.endsWith('?');\n if (isOptional) key = key.slice(0, -1);\n \n const zodType = typeToZodSchemaWithRefs(value, typeDefinitions, namedSchemas, depth + 1);\n return `${key}: ${isOptional ? `${zodType}.optional()` : zodType}`;\n }).filter(Boolean);\n \n return `z.object({ ${zodProps.join(', ')} })`;\n }\n \n // Union type\n if (typeStr.includes('|') && !typeStr.includes('{')) {\n const types = splitUnionType(typeStr).map(t => typeToZodSchemaWithRefs(t.trim(), typeDefinitions, namedSchemas, depth + 1));\n if (types.length === 2 && types.includes('z.undefined()')) {\n const other = types.find(t => t !== 'z.undefined()');\n return `${other}.optional()`;\n }\n if (types.length === 2 && types.includes('z.null()')) {\n const other = types.find(t => t !== 'z.null()');\n return `${other}.nullable()`;\n }\n return `z.union([${types.join(', ')}])`;\n }\n\n // Referência a tipo não encontrado\n if (/^[A-Z]\\w*$/.test(typeStr)) {\n return 'z.any()';\n }\n\n return 'z.any()';\n}\n\n// Converte tipo TypeScript inline para Zod schema (versão sem referências - para compatibilidade)\nfunction typeToZodSchema(typeStr: string, typeDefinitions: Map<string, string>, depth = 0): string {\n if (depth > 10) return 'z.any()'; // Previne recursão infinita\n \n typeStr = typeStr.trim();\n \n // Remove Promise wrapper\n const promiseMatch = typeStr.match(/^Promise<(.+)>$/);\n if (promiseMatch) {\n typeStr = promiseMatch[1].trim();\n }\n \n // Tipos primitivos\n if (typeStr === 'string') return 'z.string()';\n if (typeStr === 'number') return 'z.number()';\n if (typeStr === 'boolean') return 'z.boolean()';\n if (typeStr === 'null') return 'z.null()';\n if (typeStr === 'undefined') return 'z.undefined()';\n if (typeStr === 'any') return 'z.any()';\n if (typeStr === 'unknown') return 'z.unknown()';\n if (typeStr === 'void') return 'z.void()';\n if (typeStr === 'Date') return 'z.date()';\n \n // String literal\n const stringLiteralMatch = typeStr.match(/^[\"'](.+)[\"']$/);\n if (stringLiteralMatch) {\n return `z.literal(\"${stringLiteralMatch[1]}\")`;\n }\n \n // Number literal\n if (/^\\d+$/.test(typeStr)) {\n return `z.literal(${typeStr})`;\n }\n \n // Array\n const arrayMatch = typeStr.match(/^(.+)\\[\\]$/) || typeStr.match(/^Array<(.+)>$/);\n if (arrayMatch) {\n return `z.array(${typeToZodSchema(arrayMatch[1], typeDefinitions, depth + 1)})`;\n }\n \n // Verifica se é uma referência a um tipo definido (antes de processar como objeto)\n if (/^[A-Z]\\w*$/.test(typeStr) && typeDefinitions.has(typeStr)) {\n const typeDef = typeDefinitions.get(typeStr)!;\n return typeToZodSchema(typeDef, typeDefinitions, depth + 1);\n }\n \n // Object inline { key: type, ... }\n if (typeStr.startsWith('{') && typeStr.endsWith('}')) {\n const inner = typeStr.slice(1, -1).trim();\n if (!inner) return 'z.object({})';\n \n const props: string[] = [];\n let currentDepth = 0;\n let current = '';\n let inString = false;\n let stringChar = '';\n \n for (let i = 0; i < inner.length; i++) {\n const char = inner[i];\n \n if (!inString && (char === '\"' || char === \"'\" || char === '`')) {\n inString = true;\n stringChar = char;\n current += char;\n } else if (inString && char === stringChar && inner[i - 1] !== '\\\\') {\n inString = false;\n current += char;\n } else if (!inString) {\n if (char === '{' || char === '<' || char === '[' || char === '(') currentDepth++;\n else if (char === '}' || char === '>' || char === ']' || char === ')') currentDepth--;\n \n if ((char === ',' || char === ';') && currentDepth === 0) {\n if (current.trim()) props.push(current.trim());\n current = '';\n } else {\n current += char;\n }\n } else {\n current += char;\n }\n }\n if (current.trim()) props.push(current.trim());\n \n const zodProps = props.map(prop => {\n // Encontra o primeiro : que não está dentro de um tipo genérico\n let colonIndex = -1;\n let depth = 0;\n for (let i = 0; i < prop.length; i++) {\n const char = prop[i];\n if (char === '<' || char === '{' || char === '[') depth++;\n else if (char === '>' || char === '}' || char === ']') depth--;\n else if (char === ':' && depth === 0) {\n colonIndex = i;\n break;\n }\n }\n \n if (colonIndex === -1) return null;\n \n let key = prop.slice(0, colonIndex).trim();\n const value = prop.slice(colonIndex + 1).trim();\n \n const isOptional = key.endsWith('?');\n if (isOptional) key = key.slice(0, -1);\n \n const zodType = typeToZodSchema(value, typeDefinitions, depth + 1);\n return `${key}: ${isOptional ? `${zodType}.optional()` : zodType}`;\n }).filter(Boolean);\n \n return `z.object({ ${zodProps.join(', ')} })`;\n }\n \n // Union type\n if (typeStr.includes('|') && !typeStr.includes('{')) {\n const types = splitUnionType(typeStr).map(t => typeToZodSchema(t.trim(), typeDefinitions, depth + 1));\n if (types.length === 2 && types.includes('z.undefined()')) {\n const other = types.find(t => t !== 'z.undefined()');\n return `${other}.optional()`;\n }\n if (types.length === 2 && types.includes('z.null()')) {\n const other = types.find(t => t !== 'z.null()');\n return `${other}.nullable()`;\n }\n return `z.union([${types.join(', ')}])`;\n }\n \n // Intersection type\n if (typeStr.includes('&') && !typeStr.includes('{')) {\n const types = typeStr.split('&').map(t => typeToZodSchema(t.trim(), typeDefinitions, depth + 1));\n return `z.intersection(${types.join(', ')})`;\n }\n \n // Referência a tipo não encontrado - retorna z.any()\n if (/^[A-Z]\\w*$/.test(typeStr)) {\n return 'z.any()';\n }\n \n return 'z.any()';\n}\n\n// Extrai definições de tipos do arquivo (suporta tipos aninhados)\nfunction extractTypeDefinitions(content: string): Map<string, string> {\n const types = new Map<string, string>();\n \n // Remove comentários para evitar falsos positivos\n const cleanContent = content\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/\\/\\/.*$/gm, '');\n \n // Captura: type Name = { ... } ou interface Name { ... }\n // Usa uma abordagem mais robusta para capturar objetos aninhados\n const typeRegex = /(?:export\\s+)?(?:type|interface)\\s+(\\w+)\\s*=?\\s*\\{/g;\n \n let match;\n while ((match = typeRegex.exec(cleanContent)) !== null) {\n const name = match[1];\n const startIndex = match.index + match[0].length - 1; // Posição do {\n \n // Encontra o } correspondente\n let depth = 1;\n let endIndex = startIndex + 1;\n \n while (depth > 0 && endIndex < cleanContent.length) {\n const char = cleanContent[endIndex];\n if (char === '{') depth++;\n else if (char === '}') depth--;\n endIndex++;\n }\n \n const body = cleanContent.slice(startIndex, endIndex);\n types.set(name, body);\n }\n \n return types;\n}\n\n// Extrai rotas usando regex (muito mais rápido que TypeScript parser)\nfunction extractRoutes(\n content: string, \n typeDefinitions: Map<string, string>,\n namedSchemas: Map<string, string>\n): RouteInfo[] {\n const routes: RouteInfo[] = [];\n \n // Regex para capturar app.get/post/etc ou get/post/etc\n const routeRegex = /(?:app\\.)?(get|post|put|del|patch)\\s*\\(\\s*[\"'`]([^\"'`]+)[\"'`]/g;\n \n let match;\n while ((match = routeRegex.exec(content)) !== null) {\n const [fullMatch, method, routePath] = match;\n \n // Procura o bloco da rota após o match\n const afterMatch = content.slice(match.index + fullMatch.length, match.index + fullMatch.length + 2000);\n \n let returnType = 'z.any()';\n let schemaName: string | undefined;\n \n // Tenta encontrar tipo explícito: Promise<TypeName> ou Promise<{...}>\n const explicitTypeMatch = afterMatch.match(/route\\s*:\\s*async\\s*\\([^)]*\\)\\s*:\\s*Promise\\s*<([^>]+)>/);\n if (explicitTypeMatch) {\n const typeRef = explicitTypeMatch[1].trim();\n \n // Verifica se é uma referência a um tipo definido\n if (typeDefinitions.has(typeRef)) {\n // Garante que o tipo seja processado com referências\n if (!namedSchemas.has(typeRef)) {\n const typeDef = typeDefinitions.get(typeRef)!;\n namedSchemas.set(typeRef, typeToZodSchemaWithRefs(typeDef, typeDefinitions, namedSchemas));\n }\n returnType = `namedSchemas.${typeRef}`;\n schemaName = typeRef;\n } else {\n // Tipo inline\n returnType = typeToZodSchemaWithRefs(typeRef, typeDefinitions, namedSchemas);\n }\n } else {\n // Tenta inferir do return statement\n const returnMatch = afterMatch.match(/return\\s+(\\{[^}]+\\})/);\n if (returnMatch) {\n returnType = inferTypeFromValue(returnMatch[1]);\n }\n }\n\n routes.push({\n path: routePath,\n method: method === 'del' ? 'delete' : method,\n returnType,\n schemaName,\n hasFormData: content.includes('formData'),\n });\n }\n \n return routes;\n}\n\n// Infere tipo Zod a partir de um valor literal\nfunction inferTypeFromValue(value: string): string {\n value = value.trim();\n \n // Objeto literal\n if (value.startsWith('{') && value.endsWith('}')) {\n const inner = value.slice(1, -1).trim();\n if (!inner) return 'z.object({})';\n \n const props: string[] = [];\n \n // Parse simples de propriedades\n const propRegex = /(\\w+)\\s*:\\s*(\"[^\"]*\"|'[^']*'|`[^`]*`|\\d+|true|false|null|\\{[^}]*\\}|\\[[^\\]]*\\])/g;\n let propMatch;\n \n while ((propMatch = propRegex.exec(inner)) !== null) {\n const [, key, val] = propMatch;\n const zodType = inferTypeFromValue(val);\n props.push(`${key}: ${zodType}`);\n }\n \n if (props.length > 0) {\n return `z.object({ ${props.join(', ')} })`;\n }\n }\n \n // String literal\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\")) ||\n (value.startsWith('`') && value.endsWith('`'))) {\n return 'z.string()';\n }\n \n // Number\n if (/^\\d+(\\.\\d+)?$/.test(value)) {\n return 'z.number()';\n }\n \n // Boolean\n if (value === 'true' || value === 'false') {\n return 'z.boolean()';\n }\n \n // Null\n if (value === 'null') {\n return 'z.null()';\n }\n \n // Array\n if (value.startsWith('[') && value.endsWith(']')) {\n return 'z.array(z.any())';\n }\n \n return 'z.any()';\n}\n\nexport async function generateSwaggerTypes(options: GenerateSwaggerTypesOptions) {\n const { controllersPath, outputPath } = options;\n\n const routes: RouteInfo[] = [];\n const namedSchemas: Map<string, string> = new Map();\n\n // Usa Bun.Glob para listar arquivos\n const glob = new Bun.Glob('**/*.ts');\n const files: string[] = [];\n \n for await (const file of glob.scan({ cwd: controllersPath, absolute: true })) {\n const name = path.basename(file);\n if (name !== 'index.ts' && name !== 'registry.ts') {\n files.push(file);\n }\n }\n \n // Processa todos os arquivos em paralelo usando Bun.file\n await Promise.all(files.map(async (filePath) => {\n const file = Bun.file(filePath);\n const content = await file.text();\n \n // Extrai definições de tipos do arquivo\n const typeDefinitions = extractTypeDefinitions(content);\n \n // Adiciona TODOS os tipos definidos como schemas nomeados\n for (const [typeName, typeDef] of typeDefinitions) {\n if (!namedSchemas.has(typeName)) {\n const zodSchema = typeToZodSchemaWithRefs(typeDef, typeDefinitions, namedSchemas);\n namedSchemas.set(typeName, zodSchema);\n }\n }\n \n // Extrai rotas passando as definições de tipos\n const fileRoutes = extractRoutes(content, typeDefinitions, namedSchemas);\n \n routes.push(...fileRoutes);\n }));\n\n await writeOutput(outputPath, routes, namedSchemas);\n}\n\n// Ordena schemas por dependência (topological sort)\nfunction sortSchemasByDependency(schemas: Map<string, string>): string[] {\n const sorted: string[] = [];\n const visited = new Set<string>();\n const visiting = new Set<string>();\n \n function getDependencies(schema: string): string[] {\n const deps: string[] = [];\n // Procura por referências a outros schemas: namedSchemas.TypeName ou _TypeName\n const refMatches = schema.matchAll(/(?:namedSchemas\\.|_)([A-Z]\\w*)/g);\n for (const match of refMatches) {\n if (schemas.has(match[1])) {\n deps.push(match[1]);\n }\n }\n return deps;\n }\n \n function visit(name: string) {\n if (visited.has(name)) return;\n if (visiting.has(name)) return; // Ciclo detectado, ignora\n \n visiting.add(name);\n const schema = schemas.get(name);\n if (schema) {\n for (const dep of getDependencies(schema)) {\n visit(dep);\n }\n }\n visiting.delete(name);\n visited.add(name);\n sorted.push(name);\n }\n \n for (const name of schemas.keys()) {\n visit(name);\n }\n \n return sorted;\n}\n\nasync function writeOutput(outputPath: string, routes: RouteInfo[], namedSchemas: Map<string, string>) {\n const namedSchemasEntries = Array.from(namedSchemas.entries());\n \n // Ordena schemas por dependência\n const sortedNames = sortSchemasByDependency(namedSchemas);\n \n // Gera cada schema como uma variável separada (para evitar referência circular)\n const schemaDeclarations = sortedNames.map(name => {\n const schema = namedSchemas.get(name)!;\n // Substitui namedSchemas.X por _X (variável local)\n const fixedSchema = schema.replace(/namedSchemas\\.([A-Z]\\w*)/g, '_$1');\n return `const _${name} = ${fixedSchema};`;\n }).join('\\n');\n \n // Gera o objeto namedSchemas referenciando as variáveis\n const namedSchemasOutput = namedSchemasEntries.length > 0\n ? `export const namedSchemas = {\\n${sortedNames.map(name => ` ${name}: _${name},`).join('\\n')}\\n} as const;\\n\\n`\n : `export const namedSchemas = {} as const;\\n\\n`;\n\n const routeSchemasOutput = routes.map((r) => {\n const hasFormDataStr = r.hasFormData ? ', hasFormData: true' : '';\n if (r.schemaName) {\n return ` \"${r.path}\": { \"${r.method}\": { schema: _${r.schemaName}, ref: \"${r.schemaName}\"${hasFormDataStr} } },`;\n }\n // Substitui namedSchemas.X por _X no returnType também\n const fixedReturnType = r.returnType.replace(/namedSchemas\\.([A-Z]\\w*)/g, '_$1');\n return ` \"${r.path}\": { \"${r.method}\": { schema: ${fixedReturnType}, ref: null${hasFormDataStr} } },`;\n }).join('\\n');\n\n const output = `// Auto-generated by @zeti/framework/scripts\n// Do not edit manually\n\nimport { z } from \"zod\";\n\n${schemaDeclarations}\n\n${namedSchemasOutput}export const routeResponseSchemas: Record<string, Record<string, { schema: z.ZodTypeAny; ref: string | null; hasFormData?: boolean }>> = {\n${routeSchemasOutput}\n};\n`;\n\n const file = Bun.file(outputPath);\n \n try {\n if (await file.exists()) {\n const existing = await file.text();\n if (existing === output) {\n console.log(`✅ Response schemas unchanged (${routes.length} routes)`);\n return;\n }\n }\n } catch {\n // Arquivo não existe\n }\n\n await Bun.write(outputPath, output);\n console.log(`✅ Generated response schemas for ${routes.length} routes (${namedSchemasEntries.length} named schemas)`);\n}\n","import path from 'path';\nimport { generateRegistry } from './generate-registry.js';\nimport { generateSwaggerTypes } from './generate-swagger-types.js';\nimport type { ZetiConfigInternal } from '../types/config.js';\n\nexport interface RunPrebuildOptions {\n projectRoot?: string;\n zetiConfig?: ZetiConfigInternal;\n controllersPath?: string;\n registryPath?: string;\n swaggerOutputPath?: string;\n prismaImport?: string;\n /** Forçar regeneração mesmo se não houver mudanças */\n force?: boolean;\n}\n\nconst CACHE_FILE = '.zeti/.prebuild-cache.json';\n\nasync function getFileHash(filePath: string): Promise<string> {\n try {\n const file = Bun.file(filePath);\n const stat = await file.stat();\n return `${stat.mtime}-${stat.size}`;\n } catch {\n return '';\n }\n}\n\nasync function loadCache(projectRoot: string): Promise<Map<string, string>> {\n const cachePath = path.join(projectRoot, CACHE_FILE);\n try {\n const file = Bun.file(cachePath);\n if (await file.exists()) {\n const data = await file.json();\n return new Map(Object.entries(data));\n }\n } catch {\n // Cache corrupto, ignora\n }\n return new Map();\n}\n\nasync function saveCache(projectRoot: string, cache: Map<string, string>): Promise<void> {\n const cachePath = path.join(projectRoot, CACHE_FILE);\n try {\n await Bun.write(cachePath, JSON.stringify(Object.fromEntries(cache)));\n } catch {\n // Falha ao salvar cache não é crítico\n }\n}\n\nasync function hasChanges(controllersPath: string, cache: Map<string, string>): Promise<{ changed: boolean; newCache: Map<string, string> }> {\n const newCache = new Map<string, string>();\n let changed = false;\n\n // Verifica se a pasta existe\n const dirFile = Bun.file(controllersPath);\n try {\n await dirFile.stat();\n } catch {\n return { changed: cache.size > 0, newCache };\n }\n\n // Lista todos os arquivos .ts recursivamente usando Bun.Glob\n const glob = new Bun.Glob('**/*.ts');\n const files: string[] = [];\n \n for await (const file of glob.scan({ cwd: controllersPath, absolute: true })) {\n const name = path.basename(file);\n if (name !== 'index.ts' && name !== 'registry.ts') {\n files.push(file);\n }\n }\n\n // Processa em paralelo\n await Promise.all(files.map(async (file) => {\n const hash = await getFileHash(file);\n newCache.set(file, hash);\n\n if (cache.get(file) !== hash) {\n changed = true;\n }\n }));\n\n // Verifica se algum arquivo foi removido\n for (const file of cache.keys()) {\n if (!newCache.has(file)) {\n changed = true;\n break;\n }\n }\n\n return { changed, newCache };\n}\n\nconst APP_FILE_CONTENT = `import { createAppProxy, getRedisClient, hasRedis } from 'zeti-framework-backend';\nimport type { PrismaClient } from '@prisma/client';\nimport type { Redis } from 'ioredis';\n\nexport const app = createAppProxy<PrismaClient, any>();\n\n/**\n * Cliente Redis singleton via Proxy.\n * Disponível após configuração em startZeti({ redis: {...} }).\n * \n * @example\n * import { app, redis } from '@zeti/app';\n * \n * await redis.set('key', 'value');\n * const value = await redis.get('key');\n */\nexport const redis: Redis = new Proxy({} as Redis, {\n get(_, prop) {\n if (!hasRedis()) {\n throw new Error('[Redis] Not configured. Add redis config to startZeti()');\n }\n const client = getRedisClient();\n const value = (client as any)[prop];\n return typeof value === 'function' ? value.bind(client) : value;\n }\n});\n\nexport const { get, post, put, del, patch, createMiddleware } = app;\n`;\n\nconst PRISMA_HELPERS_CONTENT = `/**\n * Helpers tipados para o PrismaClient do projeto\n * \n * Gerado automaticamente pelo zeti-framework-backend.\n * Use estes helpers em middlewares e outros lugares onde\n * o tipo do PrismaClient não é inferido automaticamente.\n */\n\nimport type { Context, Next } from 'hono';\nimport type { PrismaClient } from '@prisma/client';\nimport { \n getPrismaClient as _getPrismaClient, \n getSpecialDatabase as _getSpecialDatabase,\n createMiddleware as _createMiddleware,\n} from 'zeti-framework-backend';\nimport type { MiddlewareHandler as _MiddlewareHandler } from 'zeti-framework-backend';\n\n// Re-exporta o tipo do PrismaClient\nexport type { PrismaClient };\nexport type AppPrismaClient = PrismaClient;\n\n/**\n * Handler de middleware tipado com o PrismaClient do projeto.\n */\nexport type MiddlewareHandler = _MiddlewareHandler<PrismaClient>;\n\n/**\n * Cria um middleware com o db tipado automaticamente.\n * \n * @example\n * import { createMiddleware } from '.zeti/prisma';\n * \n * export const authMiddleware = createMiddleware(async (c, next, db) => {\n * // db já vem tipado com os models do schema.prisma\n * const user = await db.user.findUnique({\n * where: { id: c.req.header('x-user-id') }\n * });\n * \n * if (!user) {\n * return c.json({ error: 'Unauthorized' }, 401);\n * }\n * \n * c.set('user', user);\n * await next();\n * });\n */\nexport function createMiddleware(\n handler: MiddlewareHandler\n): (c: Context, next: Next) => Promise<void | Response> {\n return _createMiddleware<PrismaClient>(handler);\n}\n\n/**\n * Cria uma factory de middleware com db tipado.\n * \n * @example\n * import { createMiddlewareFactory } from '.zeti/prisma';\n * \n * const requirePermission = createMiddlewareFactory(\n * (permissions: string[]) => async (c, next, db) => {\n * const user = c.get('user');\n * const userPerms = await db.permission.findMany({\n * where: { userId: user.id }\n * });\n * \n * if (!permissions.every(p => userPerms.some(up => up.name === p))) {\n * return c.json({ error: 'Forbidden' }, 403);\n * }\n * \n * await next();\n * }\n * );\n * \n * // Uso:\n * app.use('/admin/*', requirePermission(['admin:read']));\n */\nexport function createMiddlewareFactory<T extends any[]>(\n factory: (...args: T) => MiddlewareHandler\n): (...args: T) => (c: Context, next: Next) => Promise<void | Response> {\n return (...args: T) => _createMiddleware<PrismaClient>(factory(...args));\n}\n\n/**\n * Retorna o PrismaClient com tipagem correta do projeto\n * \n * @param tenantId - ID do tenant (opcional, usa o padrão se não fornecido)\n * @returns PrismaClient tipado com os models do schema.prisma\n * \n * @example\n * const db = getPrismaClient();\n * const users = await db.user.findMany(); // ✅ Tipado corretamente\n */\nexport function getPrismaClient(tenantId?: string): PrismaClient {\n return _getPrismaClient<PrismaClient>(tenantId);\n}\n\n/**\n * Retorna um database especial com tipagem correta\n * \n * @param key - Chave do database especial configurado em specialDatabases\n * @returns PrismaClient tipado\n * \n * @example\n * const adminDb = getSpecialDatabase('admin');\n * const logs = await adminDb.auditLog.findMany();\n */\nexport function getSpecialDatabase(key: string): PrismaClient {\n return _getSpecialDatabase<PrismaClient>(key);\n}\n`;\n\nasync function ensureAppFile(zetiDir: string, prismaImport: string): Promise<boolean> {\n const appPath = path.join(zetiDir, 'app.ts');\n const expectedContent = APP_FILE_CONTENT.replace('@prisma/client', prismaImport);\n \n try {\n const file = Bun.file(appPath);\n if (await file.exists()) {\n const currentContent = await file.text();\n if (currentContent === expectedContent) {\n return false; // Não mudou\n }\n }\n } catch {\n // Arquivo não existe ou erro ao ler\n }\n \n await Bun.write(appPath, expectedContent);\n return true;\n}\n\nasync function ensurePrismaHelpersFile(zetiDir: string, prismaImport: string): Promise<boolean> {\n const helpersPath = path.join(zetiDir, 'prisma.ts');\n const expectedContent = PRISMA_HELPERS_CONTENT.replace(/@prisma\\/client/g, prismaImport);\n \n try {\n const file = Bun.file(helpersPath);\n if (await file.exists()) {\n const currentContent = await file.text();\n if (currentContent === expectedContent) {\n return false; // Não mudou\n }\n }\n } catch {\n // Arquivo não existe ou erro ao ler\n }\n \n await Bun.write(helpersPath, expectedContent);\n return true;\n}\n\nexport async function runPrebuild(options: RunPrebuildOptions = {}): Promise<void> {\n const startTime = Bun.nanoseconds();\n const projectRoot = path.resolve(options.projectRoot || process.cwd());\n const zetiConfig = options.zetiConfig;\n\n const controllersPath = path.join(\n projectRoot,\n options.controllersPath || 'src/controllers'\n );\n const zetiDir = path.join(projectRoot, '.zeti');\n const registryPath = path.join(zetiDir, 'registry.ts');\n const swaggerOutputPath =\n options.swaggerOutputPath ||\n (zetiConfig?.swagger?.outputPath\n ? path.isAbsolute(zetiConfig.swagger.outputPath)\n ? zetiConfig.swagger.outputPath\n : path.join(projectRoot, zetiConfig.swagger.outputPath)\n : path.join(zetiDir, 'generated/swagger-schemas.ts'));\n\n // Garante que a pasta .zeti existe\n const fs = await import('fs');\n if (!fs.existsSync(zetiDir)) {\n fs.mkdirSync(zetiDir, { recursive: true });\n console.log('📁 [zeti] Created .zeti directory');\n }\n\n // Verifica se app.ts e prisma.ts precisam ser criados/atualizados\n const prismaImport = options.prismaImport || '@prisma/client';\n const [appChanged, prismaHelpersChanged] = await Promise.all([\n ensureAppFile(zetiDir, prismaImport),\n ensurePrismaHelpersFile(zetiDir, prismaImport),\n ]);\n\n // Carrega cache e verifica mudanças\n const cache = await loadCache(projectRoot);\n const { changed, newCache } = await hasChanges(controllersPath, cache);\n\n if (!options.force && !changed && !appChanged && !prismaHelpersChanged) {\n const elapsed = ((Bun.nanoseconds() - startTime) / 1_000_000).toFixed(0);\n console.log(`⚡ [zeti] No changes detected (${elapsed}ms)`);\n return;\n }\n\n console.log('🔄 [zeti] Generating files...');\n\n // Gera registry e swagger em paralelo\n await Promise.all([\n generateRegistry({\n controllersPath,\n indexPath: registryPath,\n outputMode: 'standalone',\n }),\n generateSwaggerTypes({\n controllersPath,\n outputPath: swaggerOutputPath,\n }),\n ]);\n\n // Salva cache\n await saveCache(projectRoot, newCache);\n\n const elapsed = ((Bun.nanoseconds() - startTime) / 1_000_000).toFixed(0);\n console.log(`✅ [zeti] Prebuild complete! (${elapsed}ms)`);\n}\n"],"mappings":"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","names":["file","path","path","path","path","elapsed"]}
|
|
File without changes
|