UNPKG

@api-buddy/prisma

Version:

Prisma database utilities for API Buddy

1 lines 11.3 kB
{"version":3,"sources":["../src/index.ts","../src/crud-generator.ts"],"sourcesContent":["/**\n * @package @api-buddy/prisma\n * Prisma database utilities for API Buddy\n */\n\n// Import PrismaClient from the generated client\nimport { PrismaClient as BasePrismaClient } from '@prisma/client';\nimport { generateCRUDRoutes, CRUDGenerator, ModelName } from './crud-generator';\n\n// Extend the PrismaClient type to include our custom methods\ndeclare module '@prisma/client' {\n interface PrismaClient {\n $connect: () => Promise<void>;\n $disconnect: () => Promise<void>;\n generateCRUDRoutes: (options: {\n outputDir: string;\n models?: ModelName[];\n exclude?: ModelName[];\n auth?: {\n required?: boolean;\n userIdField?: string;\n };\n }) => Promise<void>;\n }\n}\n\n// Create a type that includes our custom methods\ntype PrismaClientWithExtensions = BasePrismaClient & {\n crud: CRUDGenerator;\n generateCRUDRoutes: (options: {\n outputDir: string;\n models?: ModelName[];\n exclude?: ModelName[];\n auth?: {\n required?: boolean;\n userIdField?: string;\n };\n }) => Promise<void>;\n};\n\n/**\n * Extended Prisma client with API Buddy specific functionality\n */\nexport class PrismaService implements PrismaClientWithExtensions {\n // The underlying Prisma client instance\n private prisma: BasePrismaClient;\n \n // Logger for the service\n private logger: {\n info: (message: string) => void;\n error: (message: string, error?: any) => void;\n };\n\n /**\n * CRUD generator instance for this client\n */\n public readonly crud: CRUDGenerator;\n\n // Implement PrismaClient methods\n public $connect: () => Promise<void>;\n public $disconnect: () => Promise<void>;\n \n // For dynamic property access\n [key: string]: any;\n\n constructor(logger?: any) {\n // Initialize the base Prisma client\n this.prisma = new BasePrismaClient();\n \n // Set up logging\n this.logger = logger || {\n info: (message: string) => console.log(`[Prisma] ${message}`),\n error: (message: string, error?: any) => {\n const errorMessage = error ? `${message}: ${error.message || error}` : message;\n console.error(`[Prisma] ${errorMessage}`);\n if (error?.stack) {\n console.error(error.stack);\n }\n }\n };\n \n // Initialize CRUD generator with the Prisma client instance\n this.crud = new CRUDGenerator(this.prisma);\n \n // Bind Prisma client methods\n this.$connect = this.prisma.$connect.bind(this.prisma);\n this.$disconnect = this.prisma.$disconnect.bind(this.prisma);\n \n // Create a proxy to handle method calls\n return new Proxy(this, {\n get: (target, prop) => {\n // Handle our custom methods and properties first\n if (prop in target) {\n return (target as any)[prop];\n }\n // Delegate to Prisma client\n return (this.prisma as any)[prop];\n }\n }) as unknown as PrismaService;\n }\n\n /**\n * Connect to the database with error handling\n */\n async connect() {\n try {\n await this.$connect();\n this.logger.info('Successfully connected to the database');\n } catch (error) {\n this.logger.error('Failed to connect to the database', error);\n throw error;\n }\n }\n\n /**\n * Disconnect from the database\n */\n async disconnect() {\n try {\n await this.$disconnect();\n this.logger.info('Successfully disconnected from the database');\n } catch (error) {\n this.logger.error('Error disconnecting from the database', error);\n }\n }\n \n /**\n * Generate CRUD routes for your Prisma models\n * @param options Generation options\n */\n async generateCRUDRoutes(options: {\n outputDir: string;\n models?: ModelName[];\n exclude?: ModelName[];\n auth?: {\n required?: boolean;\n userIdField?: string;\n };\n }): Promise<void> {\n return this.crud.generateCRUDRoutes({\n outputDir: options.outputDir,\n models: options.models,\n exclude: options.exclude,\n auth: options.auth\n });\n }\n}\n\n/**\n * Create a new Prisma service instance\n * @param logger Optional logger implementation\n * @returns PrismaService instance with CRUD capabilities\n */\nexport function createPrismaService(logger?: any): PrismaService {\n return new PrismaService(logger);\n}\n\n// Re-export Prisma client types and utilities\nexport * from '@prisma/client';\n\n// Export our custom types and utilities\nexport * from './crud-generator';\n\n// Export the PrismaService as the default export\nexport default PrismaService;\n","import { PrismaClient as BasePrismaClient } from '@prisma/client';\nimport { writeFileSync, mkdirSync, existsSync } from 'fs';\nimport { join } from 'path';\n\n// Define our model name type\nexport type ModelName = string;\n\n// Type for the Prisma client with our custom methods\ntype PrismaClient = BasePrismaClient & {\n $connect: () => Promise<void>;\n $disconnect: () => Promise<void>;\n};\n\ninterface GenerateCRUDOptions {\n outputDir: string;\n models?: ModelName[];\n exclude?: ModelName[];\n auth?: {\n required?: boolean;\n userIdField?: string;\n };\n}\n\nexport class CRUDGenerator {\n constructor(private prisma: PrismaClient) {}\n\n private getModelNames(): ModelName[] {\n // This is a simplified implementation\n // In a real implementation, you'd parse the Prisma schema\n return [];\n }\n\n private getModelFields(model: string): string[] {\n // This is a simplified version - in a real implementation, you'd want to\n // introspect the Prisma schema to get the actual fields\n const modelName = model as keyof typeof this.prisma;\n const modelClient = this.prisma[modelName] as any;\n \n if (!modelClient) return [];\n \n // Get the first item to infer fields (simplified for example)\n // In a real implementation, you'd parse the Prisma schema\n return ['id', 'createdAt', 'updatedAt'];\n }\n\n private generateRouteContent(model: string, fields: string[]): string {\n const modelLower = model.toLowerCase();\n const modelId = `${modelLower}Id`;\n\n return `// Generated by @api-buddy/prisma\nimport { NextResponse } from 'next/server';\nimport { prisma } from '@/lib/prisma';\n\n// GET /api/${modelLower}\nexport async function GET() {\n try {\n const items = await prisma.${modelLower}.findMany();\n return NextResponse.json(items);\n } catch (error) {\n return NextResponse.json(\n { error: 'Failed to fetch ${modelLower}s' },\n { status: 500 }\n );\n }\n}\n\n// POST /api/${modelLower}\nexport async function POST(request: Request) {\n try {\n const data = await request.json();\n const item = await prisma.${modelLower}.create({ data });\n return NextResponse.json(item, { status: 201 });\n } catch (error) {\n return NextResponse.json(\n { error: 'Failed to create ${modelLower}' },\n { status: 500 }\n );\n }\n}\n`;\n }\n\n async generateCRUDRoutes(options: GenerateCRUDOptions) {\n const { outputDir, models, exclude = [], auth } = options;\n \n // Create output directory if it doesn't exist\n if (!existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Determine which models to generate routes for\n const targetModels = models || this.getModelNames();\n const filteredModels = targetModels.filter(\n (model) => !exclude.includes(model)\n );\n\n // Generate route files\n for (const model of filteredModels) {\n const modelName = String(model);\n const fields = this.getModelFields(modelName);\n const content = this.generateRouteContent(modelName, fields);\n const routePath = join(outputDir, modelName.toLowerCase(), 'route.ts');\n \n // Create model directory if it doesn't exist\n const modelDir = join(outputDir, modelName.toLowerCase());\n if (!existsSync(modelDir)) {\n mkdirSync(modelDir, { recursive: true });\n }\n \n writeFileSync(routePath, content);\n console.log(`✅ Generated CRUD routes for ${model} at ${routePath}`);\n }\n }\n}\n\n// Utility function to use the generator\nexport async function generateCRUDRoutes(\n prisma: PrismaClient,\n options: GenerateCRUDOptions\n) {\n const generator = new CRUDGenerator(prisma);\n return generator.generateCRUDRoutes(options);\n}\n"],"mappings":"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","names":["BasePrismaClient","writeFileSync","mkdirSync","existsSync","join","CRUDGenerator","prisma","model","modelName","fields","modelLower","modelId","options","outputDir","models","exclude","auth","filteredModels","content","routePath","modelDir","generateCRUDRoutes","PrismaService","logger","BasePrismaClient","message","error","errorMessage","CRUDGenerator","target","prop","options","createPrismaService","index_default"]}