crudora 0.2.0 → 0.3.0
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/cli.js +55 -65
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +1732 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +438 -0
- package/dist/index.d.ts +438 -15
- package/dist/index.js +1725 -27
- package/dist/index.js.map +1 -1
- package/dist/scripts/copy-assets.js +0 -21
- package/package.json +5 -4
- package/scripts/copy-assets.js +0 -21
- package/dist/core/crudora.d.ts +0 -49
- package/dist/core/crudora.d.ts.map +0 -1
- package/dist/core/crudora.js +0 -370
- package/dist/core/crudora.js.map +0 -1
- package/dist/core/crudoraServer.d.ts +0 -84
- package/dist/core/crudoraServer.d.ts.map +0 -1
- package/dist/core/crudoraServer.js +0 -202
- package/dist/core/crudoraServer.js.map +0 -1
- package/dist/core/drizzleTableBuilder.d.ts +0 -6
- package/dist/core/drizzleTableBuilder.d.ts.map +0 -1
- package/dist/core/drizzleTableBuilder.js +0 -175
- package/dist/core/drizzleTableBuilder.js.map +0 -1
- package/dist/core/model.d.ts +0 -58
- package/dist/core/model.d.ts.map +0 -1
- package/dist/core/model.js +0 -64
- package/dist/core/model.js.map +0 -1
- package/dist/core/repository.d.ts +0 -106
- package/dist/core/repository.d.ts.map +0 -1
- package/dist/core/repository.js +0 -607
- package/dist/core/repository.js.map +0 -1
- package/dist/core/schemaGenerator.d.ts +0 -6
- package/dist/core/schemaGenerator.d.ts.map +0 -1
- package/dist/core/schemaGenerator.js +0 -248
- package/dist/core/schemaGenerator.js.map +0 -1
- package/dist/decorators/model.d.ts +0 -64
- package/dist/decorators/model.d.ts.map +0 -1
- package/dist/decorators/model.js +0 -138
- package/dist/decorators/model.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/types/logger.type.d.ts +0 -7
- package/dist/types/logger.type.d.ts.map +0 -1
- package/dist/types/logger.type.js +0 -3
- package/dist/types/logger.type.js.map +0 -1
- package/dist/types/model.type.d.ts +0 -38
- package/dist/types/model.type.d.ts.map +0 -1
- package/dist/types/model.type.js +0 -3
- package/dist/types/model.type.js.map +0 -1
- package/dist/utils/validation.d.ts +0 -7
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/validation.js +0 -107
- package/dist/utils/validation.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/crudora.ts","../src/core/repository.ts","../src/decorators/model.ts","../src/core/schemaGenerator.ts","../src/utils/validation.ts","../src/core/drizzleTableBuilder.ts","../src/core/crudoraServer.ts","../src/core/model.ts"],"sourcesContent":["import 'reflect-metadata';\nexport { Crudora } from './core/crudora';\nexport { CrudoraServer } from './core/crudoraServer';\nexport type { CrudoraServerConfig, RateLimitConfig } from './core/crudoraServer';\nexport { Repository, NotFoundError } from './core/repository';\nexport type { FindAllOptions, FindByIdOptions, CursorPaginationOptions, CursorResult } from './core/repository';\nexport { SchemaGenerator } from './core/schemaGenerator';\nexport { DrizzleTableBuilder } from './core/drizzleTableBuilder';\nexport { ValidationGenerator } from './utils/validation';\nexport { Model } from './core/model';\nexport type { ModelConstructor } from './core/model';\nexport {\n Field,\n HasMany,\n HasOne,\n BelongsTo,\n BelongsToMany,\n getFieldMetadata,\n getRelationMetadata,\n} from './decorators/model';\nexport type { ModelOptions, FieldOptions, FieldType, Dialect, RelationDefinition, RelationType } from './types/model.type';\nexport type { CrudoraLogger } from './types/logger.type';\n","import { Express } from 'express';\nimport { z } from 'zod';\nimport { Repository, NotFoundError } from './repository';\nimport { SchemaGenerator } from './schemaGenerator';\nimport { ValidationGenerator } from '../utils/validation';\nimport { Model, ModelConstructor } from './model';\nimport { DrizzleTableBuilder } from './drizzleTableBuilder';\nimport { Dialect } from '../types/model.type';\nimport { CrudoraLogger } from '../types/logger.type';\n\nconst MAX_LIMIT = 1000;\nconst MAX_RELATIONS = 5;\n/** Validates a query-param key: alphanumeric/underscore with optional operator suffix. */\nconst SAFE_KEY_RE = /^[a-zA-Z_][a-zA-Z0-9_]*(_gt|_gte|_lt|_lte|_ne|_like|_in)?$/;\n\n// ─── Response helpers ─────────────────────────────────────────────────────────\n\nfunction ok(data: any, meta?: Record<string, any>) {\n return meta !== undefined ? { success: true, data, meta } : { success: true, data };\n}\n\nfunction fail(code: string, message: string, details?: any[]) {\n const error: Record<string, any> = { code, message };\n if (details !== undefined) error.details = details;\n return { success: false, error };\n}\n\nfunction zodDetails(issues: z.ZodError['issues']) {\n return issues.map((issue) => ({\n field: issue.path.length ? issue.path.join('.') : '_root',\n message: issue.message,\n }));\n}\n\nexport class Crudora {\n private db: any;\n private dialect: Dialect;\n private logger: CrudoraLogger | undefined;\n private models: Map<string, ModelConstructor> = new Map();\n private tables: Map<string, any> = new Map();\n private repositories: Map<string, Repository<any>> = new Map();\n private customRoutes: Array<{\n method: string;\n path: string;\n handlers: Array<(req: any, res: any, next?: any) => void>;\n }> = [];\n\n constructor(db: any, dialect: Dialect, logger?: CrudoraLogger) {\n if (!db) {\n throw new Error(\n 'Crudora: db is required. Provide a Drizzle db instance:\\n' +\n ' import { drizzle } from \"drizzle-orm/node-postgres\";\\n' +\n ' import { Pool } from \"pg\";\\n' +\n ' const db = drizzle(new Pool({ connectionString: process.env.DATABASE_URL }));',\n );\n }\n if (typeof db.select !== 'function' || typeof db.insert !== 'function') {\n throw new Error(\n 'Crudora: the provided db object does not look like a Drizzle ORM instance. ' +\n 'Make sure drizzle-orm is installed (npm install drizzle-orm) and that you are ' +\n 'passing the result of drizzle(pool) or drizzle(client), not a raw pool/connection.',\n );\n }\n this.db = db;\n this.dialect = dialect;\n this.logger = logger;\n }\n\n registerModel(...modelClasses: ModelConstructor[]): this {\n for (const modelClass of modelClasses) {\n const table = DrizzleTableBuilder.build(modelClass, this.dialect);\n // Pass the shared repositories Map so each repo can resolve siblings lazily\n const repository = new Repository(modelClass, this.db, table, this.repositories);\n this.models.set(modelClass.name, modelClass);\n this.tables.set(modelClass.name, table);\n this.repositories.set(modelClass.name, repository);\n }\n return this;\n }\n\n /**\n * Register a model against a pre-built Drizzle table object (e.g. from `drizzle-kit introspect`).\n * Skips `DrizzleTableBuilder` — useful when the database already exists and the schema\n * was generated via introspection rather than Crudora decorators.\n *\n * Validation works if the model defines `@Field()` decorators matching the table columns.\n * Without decorators, POST/PUT bodies pass through without Zod validation.\n */\n registerTable<T extends Model>(modelClass: ModelConstructor<T>, table: any): this {\n const repository = new Repository(modelClass, this.db, table, this.repositories);\n this.models.set(modelClass.name, modelClass);\n this.tables.set(modelClass.name, table);\n this.repositories.set(modelClass.name, repository);\n return this;\n }\n\n getRepository<T extends Model>(modelClass: ModelConstructor<T>): Repository<T> {\n const repository = this.repositories.get(modelClass.name);\n if (!repository) {\n throw new Error(`Repository for ${modelClass.name} not found. Did you register the model?`);\n }\n return repository;\n }\n\n /**\n * Returns the Drizzle table object for a registered model.\n * Useful for raw queries that need access to columns excluded by `hidden`\n * (e.g. fetching a password hash for authentication).\n *\n * @example\n * const usersTable = crudora.getTable(User);\n * const [row] = await db.select().from(usersTable).where(eq(usersTable.email, email)).limit(1);\n */\n getTable<T extends Model>(modelClass: ModelConstructor<T>): any {\n const table = this.tables.get(modelClass.name);\n if (!table) {\n throw new Error(`Table for ${modelClass.name} not found. Did you register the model?`);\n }\n return table;\n }\n\n generateDrizzleSchema(): string {\n const modelClasses = Array.from(this.models.values());\n return SchemaGenerator.generateDrizzleSchema(modelClasses, this.dialect);\n }\n\n getValidationSchema<T extends Model>(modelClass: ModelConstructor<T>): z.ZodType<Partial<T>> {\n return ValidationGenerator.generateZodSchema(modelClass as any);\n }\n\n getStrictValidationSchema<T extends Model>(modelClass: ModelConstructor<T>): z.ZodType<T> {\n return ValidationGenerator.generateStrictZodSchema(modelClass as any);\n }\n\n get(path: string, ...handlers: Array<(req: any, res: any, next?: any) => void>): this {\n this.customRoutes.push({ method: 'GET', path, handlers });\n return this;\n }\n\n post(path: string, ...handlers: Array<(req: any, res: any, next?: any) => void>): this {\n this.customRoutes.push({ method: 'POST', path, handlers });\n return this;\n }\n\n put(path: string, ...handlers: Array<(req: any, res: any, next?: any) => void>): this {\n this.customRoutes.push({ method: 'PUT', path, handlers });\n return this;\n }\n\n delete(path: string, ...handlers: Array<(req: any, res: any, next?: any) => void>): this {\n this.customRoutes.push({ method: 'DELETE', path, handlers });\n return this;\n }\n\n patch(path: string, ...handlers: Array<(req: any, res: any, next?: any) => void>): this {\n this.customRoutes.push({ method: 'PATCH', path, handlers });\n return this;\n }\n\n /** Runs `fn` inside a database transaction and returns its result. */\n async transaction<R>(fn: (db: any) => Promise<R>): Promise<R> {\n return this.db.transaction(fn);\n }\n\n generateRoutes(app: Express, basePath: string = '/api'): void {\n // Route discovery endpoint\n app.get(basePath, (_req, res) => {\n const routes: any[] = [];\n\n for (const [, modelClass] of this.models) {\n const routePath = `${basePath}/${modelClass.getTableName()}`;\n routes.push(\n { method: 'GET', path: routePath, description: `List all ${modelClass.getTableName()}`, type: 'CRUD' },\n { method: 'GET', path: `${routePath}/:id`, description: `Get ${modelClass.getTableName()} by ID`, type: 'CRUD' },\n { method: 'POST', path: routePath, description: `Create new ${modelClass.getTableName()}`, type: 'CRUD' },\n { method: 'PUT', path: `${routePath}/:id`, description: `Replace ${modelClass.getTableName()} by ID`, type: 'CRUD' },\n { method: 'PATCH', path: `${routePath}/:id`, description: `Partial update ${modelClass.getTableName()} by ID`, type: 'CRUD' },\n { method: 'DELETE', path: `${routePath}/:id`, description: `Delete ${modelClass.getTableName()} by ID`, type: 'CRUD' },\n );\n }\n\n for (const route of this.customRoutes) {\n routes.push({\n method: route.method,\n path: `${basePath}${route.path}`,\n description: `Custom ${route.method} route`,\n type: 'Custom',\n });\n }\n\n res.json(ok({ routes }));\n });\n\n // CRUD routes per model\n for (const [, modelClass] of this.models) {\n const repository = this.getRepository(modelClass);\n const validationSchema = this.getValidationSchema(modelClass);\n const strictValidationSchema = this.getStrictValidationSchema(modelClass);\n const routePath = `${basePath}/${modelClass.getTableName()}`;\n\n // ── GET /resource ──────────────────────────────────────────────────────\n app.get(routePath, async (req, res) => {\n try {\n const {\n page,\n limit = '10',\n orderBy,\n order,\n cursor, // presence triggers cursor mode\n cursorField,\n select, // comma-separated field names\n with: withStr, // comma-separated relation names\n withDeleted,\n ...filters\n } = req.query as Record<string, string>;\n\n const selectFields = select\n ? select.split(',').map((f) => f.trim()).filter((f) => SAFE_KEY_RE.test(f))\n : undefined;\n const withRelations = withStr\n ? withStr.split(',').map((r) => r.trim()).filter((r) => SAFE_KEY_RE.test(r)).slice(0, MAX_RELATIONS)\n : undefined;\n\n // Sanitize filter keys to prevent prototype pollution\n const safeFilters: Record<string, string> = {};\n for (const [k, v] of Object.entries(filters)) {\n if (SAFE_KEY_RE.test(k)) safeFilters[k] = v;\n }\n const whereFilters = Object.keys(safeFilters).length ? safeFilters : undefined;\n\n // Clamp limit: reject NaN, 0, negatives; cap at MAX_LIMIT\n const rawLimit = Number(limit);\n const limitNum = Number.isFinite(rawLimit) && rawLimit > 0\n ? Math.min(rawLimit, MAX_LIMIT)\n : 10;\n const includeDeleted = withDeleted === 'true';\n\n // Multiple orderBy: ?orderBy=createdAt,name&order=desc,asc\n const orderByFields = orderBy ? orderBy.split(',').map((f) => f.trim()).filter(Boolean) : undefined;\n const orderValues = order\n ? (order.split(',').map((o) => o.trim()).filter(Boolean) as Array<'asc' | 'desc'>)\n : undefined;\n const orderByArg = orderByFields && orderByFields.length === 1 ? orderByFields[0] : orderByFields;\n const orderArg = orderValues && orderValues.length === 1 ? orderValues[0] : orderValues;\n\n if (cursor !== undefined) {\n // ── Cursor-based pagination ────────────────────────────────────\n const result = await repository.findWithCursor({\n take: limitNum,\n cursor: cursor || null,\n cursorField,\n order: (orderValues?.[0]) ?? (order === 'desc' ? 'desc' : 'asc'),\n where: whereFilters,\n select: selectFields,\n with: withRelations,\n withDeleted: includeDeleted,\n });\n return res.json(ok(result.data, {\n cursor: { next: result.nextCursor, hasMore: result.hasMore },\n }));\n }\n\n // ── Offset-based pagination ────────────────────────────────────\n const rawPage = Number(page ?? 1);\n const pageNum = Number.isFinite(rawPage) && rawPage > 0 ? Math.floor(rawPage) : 1;\n const skip = (pageNum - 1) * limitNum;\n\n const items = await repository.findAll({\n skip,\n take: limitNum,\n where: whereFilters,\n orderBy: orderByArg,\n order: orderArg,\n select: selectFields,\n with: withRelations,\n withDeleted: includeDeleted,\n });\n const total = await repository.count(whereFilters, includeDeleted);\n return res.json(ok(items, {\n pagination: { page: pageNum, limit: limitNum, total, pages: total === 0 ? 0 : Math.ceil(total / limitNum) },\n }));\n } catch (err) {\n this.logger?.error('GET request failed', {\n path: routePath,\n correlationId: (req as any).correlationId,\n error: err instanceof Error ? err.message : String(err),\n });\n res.status(500).json(fail('INTERNAL_ERROR', 'Internal server error'));\n }\n });\n\n // ── GET /resource/:id ──────────────────────────────────────────────────\n app.get(`${routePath}/:id`, async (req, res) => {\n try {\n const { select, with: withStr, withDeleted } = req.query as Record<string, string>;\n const selectFields = select\n ? select.split(',').map((f) => f.trim()).filter((f) => SAFE_KEY_RE.test(f))\n : undefined;\n const withRelations = withStr\n ? withStr.split(',').map((r) => r.trim()).filter((r) => SAFE_KEY_RE.test(r)).slice(0, MAX_RELATIONS)\n : undefined;\n\n const item = await repository.findById(req.params.id, {\n select: selectFields,\n with: withRelations,\n withDeleted: withDeleted === 'true',\n });\n if (!item) return res.status(404).json(fail('NOT_FOUND', 'Resource not found'));\n return res.json(ok(item));\n } catch (err) {\n this.logger?.error('GET by ID request failed', {\n path: `${routePath}/:id`,\n id: req.params.id,\n correlationId: (req as any).correlationId,\n error: err instanceof Error ? err.message : String(err),\n });\n res.status(500).json(fail('INTERNAL_ERROR', 'Internal server error'));\n }\n });\n\n // ── POST /resource ─────────────────────────────────────────────────────\n app.post(routePath, async (req, res) => {\n try {\n const validatedData = strictValidationSchema.parse(req.body);\n const item = await repository.create(validatedData);\n return res.status(201).json(ok(item));\n } catch (error) {\n if (error instanceof z.ZodError) {\n return res.status(422).json(fail('VALIDATION_ERROR', 'Validation failed', zodDetails(error.issues)));\n }\n this.logger?.error('POST request failed', {\n path: routePath,\n correlationId: (req as any).correlationId,\n error: error instanceof Error ? error.message : String(error),\n });\n res.status(500).json(fail('INTERNAL_ERROR', 'Internal server error'));\n }\n });\n\n // ── PUT /resource/:id ──────────────────────────────────────────────────\n app.put(`${routePath}/:id`, async (req, res) => {\n try {\n const validatedData = strictValidationSchema.parse(req.body);\n const item = await repository.update(req.params.id, validatedData);\n return res.json(ok(item));\n } catch (error) {\n if (error instanceof NotFoundError) return res.status(404).json(fail('NOT_FOUND', error.message));\n if (error instanceof z.ZodError) {\n return res.status(422).json(fail('VALIDATION_ERROR', 'Validation failed', zodDetails(error.issues)));\n }\n this.logger?.error('PUT request failed', {\n path: `${routePath}/:id`,\n id: req.params.id,\n correlationId: (req as any).correlationId,\n error: error instanceof Error ? error.message : String(error),\n });\n res.status(500).json(fail('INTERNAL_ERROR', 'Internal server error'));\n }\n });\n\n // ── PATCH /resource/:id ── partial update ─────────────────────────────\n app.patch(`${routePath}/:id`, async (req, res) => {\n try {\n const validatedData = validationSchema.parse(req.body);\n const item = await repository.update(req.params.id, validatedData);\n return res.json(ok(item));\n } catch (error) {\n if (error instanceof NotFoundError) return res.status(404).json(fail('NOT_FOUND', error.message));\n if (error instanceof z.ZodError) {\n return res.status(422).json(fail('VALIDATION_ERROR', 'Validation failed', zodDetails(error.issues)));\n }\n this.logger?.error('PATCH request failed', {\n path: `${routePath}/:id`,\n id: req.params.id,\n correlationId: (req as any).correlationId,\n error: error instanceof Error ? error.message : String(error),\n });\n res.status(500).json(fail('INTERNAL_ERROR', 'Internal server error'));\n }\n });\n\n // ── DELETE /resource/:id ───────────────────────────────────────────────\n app.delete(`${routePath}/:id`, async (req, res) => {\n try {\n await repository.delete(req.params.id);\n return res.status(204).send();\n } catch (error) {\n if (error instanceof NotFoundError) return res.status(404).json(fail('NOT_FOUND', (error as Error).message));\n this.logger?.error('DELETE request failed', {\n path: `${routePath}/:id`,\n id: req.params.id,\n correlationId: (req as any).correlationId,\n error: error instanceof Error ? error.message : String(error),\n });\n res.status(500).json(fail('INTERNAL_ERROR', 'Internal server error'));\n }\n });\n }\n\n // Custom routes\n for (const route of this.customRoutes) {\n const fullPath = `${basePath}${route.path}`;\n const { method, handlers } = route;\n switch (method.toLowerCase()) {\n case 'get': app.get(fullPath, ...handlers); break;\n case 'post': app.post(fullPath, ...handlers); break;\n case 'put': app.put(fullPath, ...handlers); break;\n case 'delete': app.delete(fullPath, ...handlers); break;\n case 'patch': app.patch(fullPath, ...handlers); break;\n }\n }\n }\n}\n","import {\n eq, and, or, gt, gte, lt, lte, like, ne, inArray,\n count as drizzleCount, getTableColumns, isNull, asc, desc,\n} from 'drizzle-orm';\nimport { randomUUID } from 'crypto';\nimport { Model, ModelConstructor } from './model';\nimport { getRelationMetadata } from '../decorators/model';\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\n/** Fields managed by the ORM — never writable via user input. */\nconst SYSTEM_FIELDS = ['createdAt', 'updatedAt', 'deletedAt'] as const;\n\n/** Maximum number of values allowed in a single _in filter. */\nconst MAX_IN_VALUES = 500;\n\n/** Maximum character length for a _like search term. */\nconst MAX_LIKE_LENGTH = 200;\n\n/** Maximum number of relations that can be loaded in a single query. */\nconst MAX_RELATIONS = 5;\n\n/** Maximum rows per INSERT batch in createMany. */\nconst INSERT_BATCH_SIZE = 500;\n\n/** Validates a where-clause key: column name with optional operator suffix. */\nconst SAFE_KEY_RE = /^[a-zA-Z_][a-zA-Z0-9_]*(_gt|_gte|_lt|_lte|_ne|_like|_in)?$/;\n\n// ─── Advanced filter operators ────────────────────────────────────────────────\n\nconst OPERATOR_MAP: Record<string, (col: any, val: any) => any> = {\n _gt: (col, val) => gt(col, val),\n _gte: (col, val) => gte(col, val),\n _lt: (col, val) => lt(col, val),\n _lte: (col, val) => lte(col, val),\n _ne: (col, val) => ne(col, val),\n _like: (col, val) => like(col, `%${String(val).slice(0, MAX_LIKE_LENGTH)}%`),\n // _in splits on literal commas. Values that contain commas must be URL-encoded (%2C)\n // before reaching this layer. This is safe for UUID/integer FK values which never contain commas.\n _in: (col, val) => inArray(col, String(val).split(',').filter((v) => v !== '').slice(0, MAX_IN_VALUES)),\n};\n\n// ─── Cursor helpers ───────────────────────────────────────────────────────────\n\nfunction encodeCursor(cursorField: string, cursorValue: any, pk: string, pkValue: any): string {\n return Buffer.from(JSON.stringify({ [cursorField]: cursorValue, [pk]: pkValue })).toString('base64');\n}\n\nfunction decodeCursor(cursor: string): Record<string, any> {\n try {\n return JSON.parse(Buffer.from(cursor, 'base64').toString('utf-8'));\n } catch {\n return {};\n }\n}\n\n// ─── FindAll options ──────────────────────────────────────────────────────────\n\nexport interface FindAllOptions {\n skip?: number;\n take?: number;\n where?: Record<string, any>;\n orderBy?: string | string[];\n order?: 'asc' | 'desc' | Array<'asc' | 'desc'>;\n select?: string[];\n with?: string[];\n withDeleted?: boolean;\n /** When true, fields listed in `static hidden` are included in the result. */\n includeHidden?: boolean;\n}\n\nexport interface FindByIdOptions {\n select?: string[];\n with?: string[];\n withDeleted?: boolean;\n /** When true, fields listed in `static hidden` are included in the result. */\n includeHidden?: boolean;\n}\n\nexport interface CursorPaginationOptions {\n take?: number;\n cursor?: string | null;\n cursorField?: string;\n order?: 'asc' | 'desc';\n where?: Record<string, any>;\n select?: string[];\n with?: string[];\n withDeleted?: boolean;\n /** When true, fields listed in `static hidden` are included in the result. */\n includeHidden?: boolean;\n}\n\nexport interface CursorResult<T> {\n data: T[];\n nextCursor: string | null;\n hasMore: boolean;\n}\n\n// ─── Errors ───────────────────────────────────────────────────────────────────\n\nexport class NotFoundError extends Error {\n readonly code = 'NOT_FOUND';\n constructor(message: string) {\n super(message);\n this.name = 'NotFoundError';\n }\n}\n\n// ─── Repository ───────────────────────────────────────────────────────────────\n\nexport class Repository<T extends Model> {\n constructor(\n private modelClass: ModelConstructor<T>,\n private db: any,\n private table: any,\n /** Shared registry — same Map instance as Crudora holds; populated lazily. */\n private registry?: Map<string, Repository<any>>,\n ) {}\n\n // ─── Internal helpers ───────────────────────────────────────────────────────\n\n /**\n * Builds the Drizzle select-column object, merging hidden-field exclusion with\n * an optional explicit field list. Returns `undefined` to select all columns.\n */\n private buildSelectCols(selectFields?: string[], includeHidden = false): Record<string, any> | undefined {\n const hidden = [\n ...(includeHidden ? [] : (this.modelClass.hidden ?? [])),\n // deletedAt is an internal implementation detail — never expose it by default\n ...(this.modelClass.softDelete ? ['deletedAt'] : []),\n ];\n if (!hidden.length && !selectFields?.length) return undefined;\n\n const all = getTableColumns(this.table);\n let entries = Object.entries(all).filter(([col]) => !hidden.includes(col));\n\n if (selectFields?.length) {\n entries = entries.filter(([col]) => selectFields.includes(col));\n }\n\n return Object.fromEntries(entries);\n }\n\n private buildWhere(where?: Record<string, any>): any {\n if (!where) return undefined;\n const cols = this.table as any;\n const conds: any[] = [];\n\n for (const [key, val] of Object.entries(where)) {\n // Prototype-pollution guard + key whitelist\n if (!Object.prototype.hasOwnProperty.call(where, key)) continue;\n if (!SAFE_KEY_RE.test(key)) continue;\n if (val === undefined || val === '') continue;\n\n const suffix = Object.keys(OPERATOR_MAP).find((op) => key.endsWith(op));\n if (suffix) {\n const colName = key.slice(0, -suffix.length);\n if (Object.prototype.hasOwnProperty.call(cols, colName)) {\n conds.push(OPERATOR_MAP[suffix](cols[colName], val));\n }\n } else {\n if (Object.prototype.hasOwnProperty.call(cols, key)) {\n conds.push(eq(cols[key], val));\n }\n }\n }\n\n if (conds.length === 0) return undefined;\n return conds.length === 1 ? conds[0] : and(...conds);\n }\n\n private softDeleteClause(): any {\n if (!this.modelClass.softDelete) return undefined;\n const cols = this.table as any;\n if (!cols.deletedAt) {\n throw new Error(\n `Model \"${this.modelClass.name}\" has softDelete enabled but the table is missing a \"deletedAt\" column.`,\n );\n }\n return isNull(cols.deletedAt);\n }\n\n private combineWhere(...clauses: any[]): any {\n const active = clauses.filter(Boolean);\n if (active.length === 0) return undefined;\n if (active.length === 1) return active[0];\n return and(...active);\n }\n\n // ─── Relation loading ───────────────────────────────────────────────────────\n\n /**\n * Batch-loads relations for a list of records. Uses the _in operator so the\n * total number of DB round-trips equals the number of requested relations.\n */\n private async loadRelations(items: any[], withRelations: string[]): Promise<any[]> {\n if (!this.registry || !items.length || !withRelations.length) return items;\n\n const relDefs = getRelationMetadata(this.modelClass);\n let result = [...items];\n\n for (const relName of withRelations.slice(0, MAX_RELATIONS)) {\n const relDef = relDefs[relName];\n if (!relDef) continue;\n\n const RelModel = relDef.model();\n const relRepo = this.registry.get(RelModel.name);\n if (!relRepo) continue;\n\n const pk = this.modelClass.getPrimaryKey();\n\n if (relDef.type === 'hasMany' || relDef.type === 'hasOne') {\n const localKey = relDef.relatedKey ?? pk;\n const localVals = [...new Set<any>(result.map((r) => r[localKey]).filter(Boolean))];\n if (!localVals.length) {\n result = result.map((r) => ({ ...r, [relName]: relDef.type === 'hasOne' ? null : [] }));\n continue;\n }\n\n const related = await relRepo.findAll({\n where: { [`${relDef.foreignKey}_in`]: localVals.join(',') },\n });\n\n result = result.map((r) => {\n const matches = related.filter((rel: any) => rel[relDef.foreignKey] === r[localKey]);\n return { ...r, [relName]: relDef.type === 'hasOne' ? (matches[0] ?? null) : matches };\n });\n } else if (relDef.type === 'belongsTo') {\n const ownerKey = relDef.relatedKey ?? RelModel.getPrimaryKey();\n const fkVals = [...new Set<any>(result.map((r) => r[relDef.foreignKey]).filter(Boolean))];\n if (!fkVals.length) {\n result = result.map((r) => ({ ...r, [relName]: null }));\n continue;\n }\n\n const related = await relRepo.findAll({\n where: { [`${ownerKey}_in`]: fkVals.join(',') },\n });\n\n result = result.map((r) => {\n const match = related.find((rel: any) => rel[ownerKey] === r[relDef.foreignKey]);\n return { ...r, [relName]: match ?? null };\n });\n } else if (relDef.type === 'belongsToMany') {\n const localKey = relDef.relatedKey ?? pk;\n const localVals = [...new Set<any>(result.map((r) => r[localKey]).filter(Boolean))];\n if (!localVals.length) {\n result = result.map((r) => ({ ...r, [relName]: [] }));\n continue;\n }\n\n const PivotModel = relDef.pivotModel!();\n const pivotRepo = this.registry.get(PivotModel.name);\n if (!pivotRepo) continue;\n\n const pivotRows = await pivotRepo.findAll({\n where: { [`${relDef.foreignKey}_in`]: localVals.join(',') },\n });\n\n const relatedIds = [\n ...new Set<any>(pivotRows.map((p: any) => p[relDef.pivotRelatedKey!]).filter(Boolean)),\n ];\n if (!relatedIds.length) {\n result = result.map((r) => ({ ...r, [relName]: [] }));\n continue;\n }\n\n const relatedPk = RelModel.getPrimaryKey();\n const relatedRows = await relRepo.findAll({\n where: { [`${relatedPk}_in`]: relatedIds.join(',') },\n });\n\n result = result.map((r) => {\n const myPivots = pivotRows.filter((p: any) => p[relDef.foreignKey] === r[localKey]);\n const myIds = new Set(myPivots.map((p: any) => p[relDef.pivotRelatedKey!]));\n return { ...r, [relName]: relatedRows.filter((rel: any) => myIds.has(rel[relatedPk])) };\n });\n }\n }\n\n return result;\n }\n\n // ─── Public API ─────────────────────────────────────────────────────────────\n\n async create(data: Partial<T>): Promise<T> {\n let processed: any = { ...data };\n\n // Strip system-managed fields — never allow user to set these\n for (const f of SYSTEM_FIELDS) delete processed[f];\n\n if (this.modelClass.beforeCreate) {\n processed = await this.modelClass.beforeCreate(processed);\n }\n\n const pkField = this.modelClass.getPrimaryKey();\n if (!processed[pkField]) {\n processed[pkField] = randomUUID();\n }\n\n // Strip again after hook — prevents hook from re-injecting system fields\n for (const f of SYSTEM_FIELDS) delete processed[f];\n\n await this.db.insert(this.table).values(processed);\n const result = await this.findById(processed[pkField]);\n if (!result) throw new Error(`Create failed: could not retrieve record after insert (id: ${processed[pkField]})`);\n\n let final: any = result;\n if (this.modelClass.afterCreate) {\n final = await this.modelClass.afterCreate(processed, result);\n }\n return final;\n }\n\n async findById(id: string, opts?: FindByIdOptions): Promise<T | null> {\n const pk = this.modelClass.getPrimaryKey();\n const selectCols = this.buildSelectCols(opts?.select, opts?.includeHidden);\n\n // Note: only the `where` key of the beforeFind return value is respected here.\n // Properties like `skip`, `take`, and `orderBy` are ignored — they are only\n // meaningful in findAll(). Use afterFind to transform the result instead.\n let hookOptions: any = { where: { [pk]: id } };\n if (this.modelClass.beforeFind) {\n hookOptions = await this.modelClass.beforeFind(hookOptions);\n }\n\n const extraWhere = this.buildWhere(hookOptions?.where ? { ...hookOptions.where, [pk]: undefined } : undefined);\n\n let query = selectCols\n ? this.db.select(selectCols).from(this.table)\n : this.db.select().from(this.table);\n\n const whereClause = this.combineWhere(\n eq((this.table as any)[pk], id),\n opts?.withDeleted ? undefined : this.softDeleteClause(),\n extraWhere,\n );\n query = query.where(whereClause).limit(1);\n\n const [result] = await query;\n let found: any = result ?? null;\n\n if (found && this.modelClass.afterFind) {\n [found] = await this.modelClass.afterFind([found]);\n }\n\n if (found && opts?.with?.length) {\n const [withResult] = await this.loadRelations([found], opts.with);\n return withResult ?? null;\n }\n\n return found;\n }\n\n async findAll(options?: FindAllOptions): Promise<T[]> {\n let queryOptions = options ? { ...options } : undefined;\n if (this.modelClass.beforeFind) {\n queryOptions = await this.modelClass.beforeFind(queryOptions);\n }\n\n const selectCols = this.buildSelectCols(queryOptions?.select, queryOptions?.includeHidden);\n const whereClause = this.combineWhere(\n this.buildWhere(queryOptions?.where),\n queryOptions?.withDeleted ? undefined : this.softDeleteClause(),\n );\n\n let query = selectCols\n ? this.db.select(selectCols).from(this.table)\n : this.db.select().from(this.table);\n\n if (whereClause) query = query.where(whereClause);\n\n if (queryOptions?.orderBy) {\n const fields = Array.isArray(queryOptions.orderBy) ? queryOptions.orderBy : [queryOptions.orderBy];\n const orders = Array.isArray(queryOptions.order) ? queryOptions.order : [queryOptions.order ?? 'asc'];\n const orderClauses = fields\n .map((field, i) => {\n // Validate field name before property access to prevent prototype traversal\n if (!SAFE_KEY_RE.test(field)) return null;\n if (!Object.prototype.hasOwnProperty.call(this.table, field)) return null;\n const col = (this.table as any)[field];\n return (orders[i] ?? orders[0] ?? 'asc') === 'desc' ? desc(col) : asc(col);\n })\n .filter(Boolean);\n if (orderClauses.length) query = query.orderBy(...orderClauses);\n }\n\n if (queryOptions?.skip !== undefined) query = query.offset(queryOptions.skip);\n if (queryOptions?.take !== undefined) query = query.limit(queryOptions.take);\n\n let results: any[] = await query;\n\n if (this.modelClass.afterFind) {\n results = await this.modelClass.afterFind(results);\n }\n\n if (queryOptions?.with?.length) {\n results = await this.loadRelations(results, queryOptions.with);\n }\n\n return results;\n }\n\n /**\n * Cursor-based pagination — more efficient than offset for large datasets.\n *\n * @example\n * const page1 = await userRepo.findWithCursor({ take: 10 });\n * const page2 = await userRepo.findWithCursor({ take: 10, cursor: page1.nextCursor });\n */\n async findWithCursor(options: CursorPaginationOptions): Promise<CursorResult<T>> {\n const {\n take = 10,\n cursor,\n order = 'asc',\n where,\n select,\n with: withRelations,\n withDeleted,\n includeHidden,\n } = options;\n\n const pk = this.modelClass.getPrimaryKey();\n // Validate cursorField against known columns to prevent prototype traversal\n const requestedCursorField = options.cursorField ?? pk;\n const cursorField =\n SAFE_KEY_RE.test(requestedCursorField) &&\n Object.prototype.hasOwnProperty.call(this.table, requestedCursorField)\n ? requestedCursorField\n : pk;\n const col = (this.table as any)[cursorField];\n const pkCol = (this.table as any)[pk];\n const cursorFieldIsPk = cursorField === pk;\n\n // Decode cursor — stores both cursorField value and pk value for composite tie-breaking\n let cursorValue: any = null;\n let cursorPkValue: any = null;\n if (cursor) {\n const decoded = decodeCursor(cursor);\n cursorValue = decoded[cursorField] ?? null;\n cursorPkValue = decoded[pk] ?? null;\n }\n\n // Build cursor condition.\n // When cursorField is non-unique, use a composite condition to avoid skipping\n // rows that share the same cursorField value:\n // (cursorField > val) OR (cursorField = val AND pk > pkVal)\n let cursorCond: any = undefined;\n if (cursorValue !== null && col) {\n if (cursorFieldIsPk || cursorPkValue === null) {\n // PK is always unique — simple GT/LT is safe\n cursorCond = order === 'desc' ? lt(col, cursorValue) : gt(col, cursorValue);\n } else {\n cursorCond = or(\n order === 'desc' ? lt(col, cursorValue) : gt(col, cursorValue),\n and(\n eq(col, cursorValue),\n order === 'desc' ? lt(pkCol, cursorPkValue) : gt(pkCol, cursorPkValue),\n ),\n );\n }\n }\n\n const whereClause = this.combineWhere(\n this.buildWhere(where),\n withDeleted ? undefined : this.softDeleteClause(),\n cursorCond,\n );\n\n const selectCols = this.buildSelectCols(select, includeHidden);\n\n let query = selectCols\n ? this.db.select(selectCols).from(this.table)\n : this.db.select().from(this.table);\n\n if (whereClause) query = query.where(whereClause);\n\n // Sort by cursorField; add pk as tie-breaker when cursorField is non-unique\n if (col) {\n query = !cursorFieldIsPk && pkCol\n ? query.orderBy(order === 'desc' ? desc(col) : asc(col), order === 'desc' ? desc(pkCol) : asc(pkCol))\n : query.orderBy(order === 'desc' ? desc(col) : asc(col));\n }\n\n // Fetch one extra to detect whether there are more pages\n query = query.limit(take + 1);\n\n let results: any[] = await query;\n\n const hasMore = results.length > take;\n const data: any[] = hasMore ? results.slice(0, take) : results;\n\n const nextCursor =\n hasMore && data.length > 0\n ? encodeCursor(cursorField, data[data.length - 1][cursorField], pk, data[data.length - 1][pk])\n : null;\n\n if (this.modelClass.afterFind) {\n const processed = await this.modelClass.afterFind(data);\n const finalData = withRelations?.length\n ? await this.loadRelations(processed, withRelations)\n : processed;\n return { data: finalData, nextCursor, hasMore };\n }\n\n const finalData = withRelations?.length\n ? await this.loadRelations(data, withRelations)\n : data;\n\n return { data: finalData, nextCursor, hasMore };\n }\n\n async update(id: string, data: Partial<T>): Promise<T> {\n let processed: any = { ...data };\n\n // Strip fields that must never be overwritten by user input\n const pk = this.modelClass.getPrimaryKey();\n delete processed[pk];\n delete processed['createdAt'];\n delete processed['deletedAt'];\n\n if (this.modelClass.beforeUpdate) {\n processed = await this.modelClass.beforeUpdate(id, processed);\n }\n\n // Strip again after hook — prevents hook from re-injecting immutable fields\n delete processed[pk];\n delete processed['createdAt'];\n delete processed['deletedAt'];\n\n // Guard before timestamp injection — empty body truly short-circuits here\n if (Object.keys(processed).length === 0) {\n const existing = await this.findById(id);\n if (!existing) throw new NotFoundError(`Record with id \"${id}\" not found`);\n return existing;\n }\n\n if (this.modelClass.timestamps !== false) {\n const cols = getTableColumns(this.table);\n if ('updatedAt' in cols) {\n processed.updatedAt = new Date();\n }\n }\n\n // For soft-delete models, distinguish \"not found\" from \"soft-deleted\" before updating\n if (this.modelClass.softDelete) {\n const tbl = this.table as any;\n const [row] = await this.db\n .select({ _deleted: tbl.deletedAt })\n .from(this.table)\n .where(eq(tbl[pk], id))\n .limit(1);\n if (!row) throw new NotFoundError(`Record with id \"${id}\" not found`);\n if (row._deleted !== null && row._deleted !== undefined) {\n throw new NotFoundError(`Record with id \"${id}\" is soft-deleted and cannot be updated`);\n }\n }\n\n const updateWhere = this.combineWhere(\n eq((this.table as any)[pk], id),\n this.softDeleteClause(),\n );\n await this.db.update(this.table).set(processed).where(updateWhere);\n\n const result = await this.findById(id);\n if (!result) throw new NotFoundError(`Record with id \"${id}\" not found`);\n\n let final: any = result;\n if (this.modelClass.afterUpdate) {\n final = await this.modelClass.afterUpdate(id, processed, result);\n }\n return final;\n }\n\n async delete(id: string): Promise<T> {\n // Check existence first — beforeDelete must not fire for non-existent records\n const existing = await this.findById(id);\n if (!existing) throw new NotFoundError(`Record with id \"${id}\" not found`);\n\n if (this.modelClass.beforeDelete) {\n await this.modelClass.beforeDelete(id);\n }\n\n const pk = this.modelClass.getPrimaryKey();\n\n if (this.modelClass.softDelete) {\n await this.db\n .update(this.table)\n .set({ deletedAt: new Date() })\n .where(eq((this.table as any)[pk], id));\n } else {\n await this.db.delete(this.table).where(eq((this.table as any)[pk], id));\n }\n\n let final: any = existing;\n if (this.modelClass.afterDelete) {\n final = await this.modelClass.afterDelete(id, existing);\n }\n return final;\n }\n\n async hardDelete(id: string): Promise<T> {\n const existing = await this.findById(id, { withDeleted: true });\n if (!existing) throw new NotFoundError(`Record with id \"${id}\" not found`);\n const pk = this.modelClass.getPrimaryKey();\n await this.db.delete(this.table).where(eq((this.table as any)[pk], id));\n return existing;\n }\n\n async restore(id: string): Promise<T> {\n const pk = this.modelClass.getPrimaryKey();\n const cols = this.table as any;\n if (!cols.deletedAt) throw new Error('softDelete is not enabled on this model');\n\n // Fetch the raw row (including deletedAt) to verify it exists AND is soft-deleted\n const [raw] = await this.db.select().from(this.table)\n .where(eq(cols[pk], id)).limit(1);\n if (!raw) throw new NotFoundError(`Record with id \"${id}\" not found`);\n if (!raw.deletedAt) throw new Error(`Record with id \"${id}\" is not soft-deleted`);\n\n await this.db\n .update(this.table)\n .set({ deletedAt: null })\n .where(eq(cols[pk], id));\n\n const selectCols = this.buildSelectCols();\n let query = selectCols\n ? this.db.select(selectCols).from(this.table)\n : this.db.select().from(this.table);\n query = query.where(eq(cols[pk], id)).limit(1);\n const [result] = await query;\n return result ?? null;\n }\n\n async count(where?: any, withDeleted?: boolean): Promise<number> {\n const whereClause = this.combineWhere(\n this.buildWhere(where),\n withDeleted ? undefined : this.softDeleteClause(),\n );\n let query = this.db.select({ count: drizzleCount() }).from(this.table);\n if (whereClause) query = query.where(whereClause);\n const [result] = await query;\n return Number(result.count);\n }\n\n /** Returns the first record matching `where`, or null. Builds a direct LIMIT 1 query — does not delegate to findAll. */\n async findOne(where?: Record<string, any>, opts?: FindByIdOptions): Promise<T | null> {\n const selectCols = this.buildSelectCols(opts?.select, opts?.includeHidden);\n const whereClause = this.combineWhere(\n this.buildWhere(where),\n opts?.withDeleted ? undefined : this.softDeleteClause(),\n );\n\n let query = selectCols\n ? this.db.select(selectCols).from(this.table)\n : this.db.select().from(this.table);\n\n if (whereClause) query = query.where(whereClause);\n query = query.limit(1);\n\n const [result] = await query;\n let found: any = result ?? null;\n\n if (found && this.modelClass.afterFind) {\n [found] = await this.modelClass.afterFind([found]);\n }\n\n if (found && opts?.with?.length) {\n const [withResult] = await this.loadRelations([found], opts.with);\n return withResult ?? null;\n }\n\n return found;\n }\n\n /**\n * Returns true if at least one record matches `where`.\n * Uses SELECT pk LIMIT 1 — more efficient than COUNT(*) because the DB stops at the first match.\n */\n async exists(where?: Record<string, any>, withDeleted?: boolean): Promise<boolean> {\n const pk = this.modelClass.getPrimaryKey();\n const whereClause = this.combineWhere(\n this.buildWhere(where),\n withDeleted ? undefined : this.softDeleteClause(),\n );\n\n let query = this.db.select({ _pk: (this.table as any)[pk] }).from(this.table);\n if (whereClause) query = query.where(whereClause);\n query = query.limit(1);\n\n const [result] = await query;\n return result !== undefined;\n }\n\n /**\n * Inserts multiple records in a single INSERT statement.\n * Calls `beforeCreate` for each row. Calls `afterCreateMany` once with all\n * results — use this hook for batch-aware side effects (e.g. bulk notifications).\n * Individual `afterCreate` is intentionally NOT called per row for performance.\n */\n async createMany(data: Partial<T>[]): Promise<T[]> {\n if (data.length === 0) return [];\n\n const pk = this.modelClass.getPrimaryKey();\n\n const processed = await Promise.all(\n data.map(async (item) => {\n let row: any = { ...item };\n for (const f of SYSTEM_FIELDS) delete row[f];\n if (this.modelClass.beforeCreate) {\n row = await this.modelClass.beforeCreate(row);\n }\n // Strip again after hook — mirrors the defense-in-depth in create()\n for (const f of SYSTEM_FIELDS) delete row[f];\n if (!row[pk]) row[pk] = randomUUID();\n return row;\n }),\n );\n\n // Batch inserts to avoid DB packet/lock limits\n for (let i = 0; i < processed.length; i += INSERT_BATCH_SIZE) {\n await this.db.insert(this.table).values(processed.slice(i, i + INSERT_BATCH_SIZE));\n }\n\n // Fetch results in batches matching MAX_IN_VALUES so >500 inserts all return\n const pks = processed.map((r) => r[pk]);\n const results: T[] = [];\n for (let i = 0; i < pks.length; i += MAX_IN_VALUES) {\n const batch = pks.slice(i, i + MAX_IN_VALUES);\n const rows = await this.findAll({ where: { [`${pk}_in`]: batch.join(',') } });\n results.push(...rows);\n }\n\n // Re-order to match input insertion order — DB IN queries don't guarantee row order\n const pkOrder = new Map(pks.map((id, i) => [id, i]));\n results.sort((a, b) => (pkOrder.get((a as any)[pk]) ?? 0) - (pkOrder.get((b as any)[pk]) ?? 0));\n\n if (this.modelClass.afterCreateMany) {\n return this.modelClass.afterCreateMany(results);\n }\n return results;\n }\n\n /**\n * Runs `fn` inside a database transaction. The callback receives a new\n * Repository bound to the transaction connection.\n *\n * @example\n * await userRepo.transaction(async (trx) => {\n * await trx.create({ name: 'Alice' });\n * await trx.update(id, { name: 'Bob' });\n * });\n */\n async transaction<R>(fn: (trx: Repository<T>) => Promise<R>): Promise<R> {\n return this.db.transaction(async (trx: any) => {\n // Rebuild the registry so every relation load inside the transaction\n // uses the same transactional connection — not the outer db connection.\n //\n // Pass `trxRegistry` by reference at construction time so all repos\n // share the same Map. Lookups happen lazily (in loadRelations), so\n // the Map is fully populated before any repo needs to use it.\n let trxRegistry: Map<string, Repository<any>> | undefined;\n\n if (this.registry) {\n trxRegistry = new Map<string, Repository<any>>();\n for (const [name, repo] of this.registry.entries()) {\n trxRegistry.set(name, new Repository(repo.modelClass, trx, repo.table, trxRegistry));\n }\n }\n\n return fn(new Repository(this.modelClass, trx, this.table, trxRegistry));\n });\n }\n}\n","import 'reflect-metadata';\nimport { FieldOptions, ModelOptions, RelationDefinition, RelationType } from '../types/model.type';\n\nconst MODEL_METADATA_KEY = Symbol('model');\nconst FIELD_METADATA_KEY = Symbol('field');\n\nexport function Model(options: ModelOptions = {}) {\n return function <T extends { new (...args: any[]): {} }>(constructor: T) {\n Reflect.defineMetadata(MODEL_METADATA_KEY, {\n tableName: options.tableName || constructor.name.toLowerCase(),\n timestamps: options.timestamps !== false,\n constructor\n }, constructor);\n return constructor;\n };\n}\n\nexport function Field(options: FieldOptions) {\n return function (target: any, context: any) {\n // Support both old and new decorator syntax\n if (typeof context === 'string') {\n // Old decorator syntax (target, propertyKey)\n const propertyKey = context;\n const existingFields = Reflect.getMetadata(FIELD_METADATA_KEY, target.constructor) || {};\n existingFields[propertyKey] = options;\n Reflect.defineMetadata(FIELD_METADATA_KEY, existingFields, target.constructor);\n } else {\n // New decorator syntax (target, context)\n const propertyKey = context.name;\n const constructor = target.constructor;\n const existingFields = Reflect.getMetadata(FIELD_METADATA_KEY, constructor) || {};\n existingFields[propertyKey] = options;\n Reflect.defineMetadata(FIELD_METADATA_KEY, existingFields, constructor);\n }\n };\n}\n\nexport function getModelMetadata(target: any) {\n return Reflect.getMetadata(MODEL_METADATA_KEY, target);\n}\n\nexport function getFieldMetadata(target: any) {\n return Reflect.getMetadata(FIELD_METADATA_KEY, target) || {};\n}\n\n// ─── Relation decorators ──────────────────────────────────────────────────────\n\nconst RELATION_METADATA_KEY = Symbol('relations');\n\nfunction defineRelation(type: RelationType, model: () => any, foreignKey: string, relatedKey?: string) {\n return function (target: any, propertyKey: string) {\n const constructor = target.constructor;\n const existing: Record<string, RelationDefinition> =\n Reflect.getMetadata(RELATION_METADATA_KEY, constructor) || {};\n existing[propertyKey] = { type, model, foreignKey, relatedKey };\n Reflect.defineMetadata(RELATION_METADATA_KEY, existing, constructor);\n };\n}\n\n/**\n * Declares a one-to-many relation.\n * @param model Lazy getter returning the related model constructor.\n * @param foreignKey Column on the **related** table that references this model.\n * @param localKey Column on **this** table (defaults to this model's primary key).\n *\n * @example\n * class User extends Model {\n * @HasMany(() => Post, 'authorId')\n * posts?: Post[];\n * }\n */\nexport function HasMany(model: () => any, foreignKey: string, localKey?: string) {\n return defineRelation('hasMany', model, foreignKey, localKey);\n}\n\n/**\n * Declares a one-to-one relation where the FK lives on the related table.\n * @param model Lazy getter returning the related model constructor.\n * @param foreignKey Column on the **related** table that references this model.\n * @param localKey Column on **this** table (defaults to primary key).\n *\n * @example\n * class User extends Model {\n * @HasOne(() => Profile, 'userId')\n * profile?: Profile;\n * }\n */\nexport function HasOne(model: () => any, foreignKey: string, localKey?: string) {\n return defineRelation('hasOne', model, foreignKey, localKey);\n}\n\n/**\n * Declares a many-to-one (or one-to-one) relation where the FK lives on **this** table.\n * @param model Lazy getter returning the related model constructor.\n * @param foreignKey Column on **this** table that holds the FK value.\n * @param ownerKey Column on the **related** table being pointed to (defaults to its primary key).\n *\n * @example\n * class Post extends Model {\n * @BelongsTo(() => User, 'authorId')\n * author?: User;\n * }\n */\nexport function BelongsTo(model: () => any, foreignKey: string, ownerKey?: string) {\n return defineRelation('belongsTo', model, foreignKey, ownerKey);\n}\n\n/**\n * Declares a many-to-many relation through a pivot/junction model.\n * @param model Lazy getter returning the **related** model constructor.\n * @param pivotModel Lazy getter returning the **pivot** model constructor.\n * @param pivotForeignKey Column on the pivot table that references **this** model.\n * @param pivotRelatedKey Column on the pivot table that references the **related** model.\n * @param localKey Override for this model's local key (defaults to primary key).\n *\n * @example\n * class User extends Model {\n * @BelongsToMany(() => Role, () => UserRole, 'userId', 'roleId')\n * roles?: Role[];\n * }\n */\nexport function BelongsToMany(\n model: () => any,\n pivotModel: () => any,\n pivotForeignKey: string,\n pivotRelatedKey: string,\n localKey?: string,\n) {\n return function (target: any, propertyKey: string) {\n const constructor = target.constructor;\n const existing: Record<string, RelationDefinition> =\n Reflect.getMetadata(RELATION_METADATA_KEY, constructor) || {};\n existing[propertyKey] = {\n type: 'belongsToMany',\n model,\n foreignKey: pivotForeignKey,\n relatedKey: localKey,\n pivotModel,\n pivotRelatedKey,\n };\n Reflect.defineMetadata(RELATION_METADATA_KEY, existing, constructor);\n };\n}\n\nexport function getRelationMetadata(target: any): Record<string, RelationDefinition> {\n return Reflect.getMetadata(RELATION_METADATA_KEY, target) || {};\n}\n","import { getFieldMetadata } from '../decorators/model';\nimport { Dialect, FieldOptions, FieldType } from '../types/model.type';\nimport { ModelConstructor } from './model';\n\n/** Escape single-quotes and backslashes so the string is safe inside a JS single-quoted literal. */\nfunction safe(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\nfunction pgColumnDef(name: string, opts: FieldOptions): string {\n const type: FieldType = opts.type;\n let col: string;\n\n const n = safe(name);\n switch (type) {\n case 'uuid':\n col = `uuid('${n}')`;\n break;\n case 'text':\n col = `text('${n}')`;\n break;\n case 'integer':\n col = `integer('${n}')`;\n break;\n case 'number':\n col = `doublePrecision('${n}')`;\n break;\n case 'boolean':\n col = `boolean('${n}')`;\n break;\n case 'date':\n col = `timestamp('${n}', { mode: 'date' })`;\n break;\n case 'decimal':\n col = `decimal('${n}', { precision: ${opts.precision ?? 10}, scale: ${opts.scale ?? 2} })`;\n break;\n case 'json':\n col = `json('${n}')`;\n break;\n case 'enum':\n col = `text('${n}')`;\n break;\n case 'bigint':\n col = `bigint('${n}', { mode: 'number' })`;\n break;\n case 'serial':\n col = `serial('${n}')`;\n break;\n case 'array':\n col = `text('${n}').array()`;\n break;\n case 'string':\n default:\n col = `varchar('${n}', { length: ${opts.length ?? 255} })`;\n }\n\n if (opts.primary) col += '.primaryKey()';\n if (opts.required && !opts.nullable && opts.type !== 'serial') col += '.notNull()';\n if (opts.unique) col += '.unique()';\n if (opts.default !== undefined && opts.type !== 'serial') col += `.default(${JSON.stringify(opts.default)})`;\n\n return col;\n}\n\nfunction mysqlColumnDef(name: string, opts: FieldOptions): string {\n const type: FieldType = opts.type;\n let col: string;\n\n const n = safe(name);\n switch (type) {\n case 'uuid':\n col = `varchar('${n}', { length: 36 })`;\n break;\n case 'text':\n col = `text('${n}')`;\n break;\n case 'integer':\n col = `int('${n}')`;\n break;\n case 'number':\n col = `double('${n}')`;\n break;\n case 'boolean':\n col = `boolean('${n}')`;\n break;\n case 'date':\n col = `datetime('${n}', { mode: 'date' })`;\n break;\n case 'decimal':\n col = `decimal('${n}', { precision: ${opts.precision ?? 10}, scale: ${opts.scale ?? 2} })`;\n break;\n case 'json':\n col = `json('${n}')`;\n break;\n case 'enum':\n col = `mysqlEnum('${n}', [${(opts.enumValues ?? []).map((v) => `'${safe(v)}'`).join(', ')}])`;\n break;\n case 'bigint':\n col = `bigint('${n}', { mode: 'number' })`;\n break;\n case 'serial':\n col = `int('${n}').autoincrement()`;\n break;\n case 'array':\n col = `json('${n}')`;\n break;\n case 'string':\n default:\n col = `varchar('${n}', { length: ${opts.length ?? 255} })`;\n }\n\n if (opts.primary) col += '.primaryKey()';\n if (opts.required && !opts.nullable && opts.type !== 'serial') col += '.notNull()';\n if (opts.unique) col += '.unique()';\n if (opts.default !== undefined && opts.type !== 'serial') col += `.default(${JSON.stringify(opts.default)})`;\n\n return col;\n}\n\nfunction generateModelBlock(\n modelClass: ModelConstructor,\n dialect: Dialect,\n schemaVars: Map<string, string>,\n): string {\n const fields = getFieldMetadata(modelClass) as Record<string, FieldOptions>;\n const tableName = modelClass.getTableName();\n const schemaName = (modelClass as any).schema as string | undefined;\n const exportName = modelClass.name.charAt(0).toLowerCase() + modelClass.name.slice(1) + 'Table';\n const columnDef = dialect === 'postgresql' ? pgColumnDef : mysqlColumnDef;\n\n const cols: string[] = [];\n for (const [fieldName, opts] of Object.entries(fields)) {\n cols.push(` ${fieldName}: ${columnDef(fieldName, opts)},`);\n }\n\n if (modelClass.timestamps !== false) {\n if (dialect === 'postgresql') {\n cols.push(` createdAt: timestamp('createdAt', { mode: 'date' }).defaultNow().notNull(),`);\n cols.push(` updatedAt: timestamp('updatedAt', { mode: 'date' }).defaultNow().notNull(),`);\n } else {\n cols.push(` createdAt: datetime('createdAt', { mode: 'date' }).notNull(),`);\n cols.push(` updatedAt: datetime('updatedAt', { mode: 'date' }).notNull(),`);\n }\n }\n\n if (modelClass.softDelete) {\n if (dialect === 'postgresql') {\n cols.push(` deletedAt: timestamp('deletedAt', { mode: 'date' }),`);\n } else {\n cols.push(` deletedAt: datetime('deletedAt', { mode: 'date' }),`);\n }\n }\n\n let tableCall: string;\n if (schemaName) {\n const schemaVar = schemaVars.get(schemaName)!;\n tableCall = `${schemaVar}.table('${safe(tableName)}', {\\n${cols.join('\\n')}\\n})`;\n } else {\n const tableFactory = dialect === 'postgresql' ? 'pgTable' : 'mysqlTable';\n tableCall = `${tableFactory}('${safe(tableName)}', {\\n${cols.join('\\n')}\\n})`;\n }\n\n return `export const ${exportName} = ${tableCall};\\n`;\n}\n\nexport class SchemaGenerator {\n static generateDrizzleSchema(models: ModelConstructor[], dialect: Dialect): string {\n const schemaNames = new Set<string>();\n for (const m of models) {\n const s = (m as any).schema as string | undefined;\n if (s) schemaNames.add(s);\n }\n\n // Assign variable names for each schema\n const schemaVars = new Map<string, string>();\n for (const name of schemaNames) {\n schemaVars.set(name, name + 'Schema');\n }\n\n // Collect imports\n const coreImports = new Set<string>();\n const schemaFactory = dialect === 'postgresql' ? 'pgSchema' : 'mysqlSchema';\n const tableFactory = dialect === 'postgresql' ? 'pgTable' : 'mysqlTable';\n const pkg = dialect === 'postgresql' ? 'drizzle-orm/pg-core' : 'drizzle-orm/mysql-core';\n\n if (schemaNames.size > 0) coreImports.add(schemaFactory);\n\n // Check if any model uses default (no schema) tables\n const hasDefaultSchema = models.some((m) => !(m as any).schema);\n if (hasDefaultSchema) coreImports.add(tableFactory);\n\n // Collect column builder imports\n const colImports = new Set<string>();\n for (const modelClass of models) {\n const fields = getFieldMetadata(modelClass) as Record<string, FieldOptions>;\n for (const opts of Object.values(fields)) {\n colImports.add(getColumnImport(opts.type, dialect));\n }\n if (modelClass.timestamps !== false) {\n colImports.add(dialect === 'postgresql' ? 'timestamp' : 'datetime');\n }\n }\n\n const allImports = new Set([...coreImports, ...colImports]);\n let output = `// Auto-generated by Crudora — do not edit manually\\n`;\n output += `import { ${[...allImports].sort().join(', ')} } from '${pkg}';\\n\\n`;\n\n // Schema variable declarations\n for (const [name, varName] of schemaVars) {\n output += `const ${varName} = ${schemaFactory}('${safe(name)}');\\n`;\n }\n if (schemaVars.size > 0) output += '\\n';\n\n // Model table blocks\n for (const modelClass of models) {\n output += generateModelBlock(modelClass, dialect, schemaVars) + '\\n';\n }\n\n return output;\n }\n}\n\nfunction getColumnImport(type: FieldType, dialect: Dialect): string {\n if (dialect === 'postgresql') {\n const map: Record<FieldType, string> = {\n uuid: 'uuid',\n text: 'text',\n string: 'varchar',\n integer: 'integer',\n number: 'doublePrecision',\n boolean: 'boolean',\n date: 'timestamp',\n decimal: 'decimal',\n json: 'json',\n enum: 'text',\n bigint: 'bigint',\n serial: 'serial',\n array: 'text',\n };\n return map[type] ?? 'varchar';\n } else {\n const map: Record<FieldType, string> = {\n uuid: 'varchar',\n text: 'text',\n string: 'varchar',\n integer: 'int',\n number: 'double',\n boolean: 'boolean',\n date: 'datetime',\n decimal: 'decimal',\n json: 'json',\n enum: 'mysqlEnum',\n bigint: 'bigint',\n serial: 'int',\n array: 'json',\n };\n return map[type] ?? 'varchar';\n }\n}\n","import { z } from 'zod';\nimport { Model, ModelConstructor } from '../core/model';\nimport { getFieldMetadata } from '../decorators/model';\nimport { FieldOptions, FieldType } from '../types/model.type';\n\nfunction zodTypeFor(opts: FieldOptions, forStrict: boolean): z.ZodTypeAny {\n const { type, required = false, nullable = false, length } = opts;\n let base: z.ZodTypeAny;\n switch (type) {\n case 'integer':\n base = z.number().int();\n break;\n case 'number':\n base = z.number();\n break;\n case 'boolean':\n base = z.boolean();\n break;\n case 'date':\n base = z.coerce.date();\n break;\n case 'decimal':\n base = z.string().regex(/^-?\\d+(\\.\\d+)?$/, 'Must be a valid decimal number');\n break;\n case 'json':\n base = z.union([z.record(z.string(), z.any()), z.array(z.any())]);\n break;\n case 'uuid':\n base = z.uuid();\n break;\n case 'enum':\n base = opts.enumValues?.length\n ? z.enum(opts.enumValues as [string, ...string[]])\n : z.string();\n break;\n case 'bigint':\n base = z.number().int();\n break;\n case 'serial':\n base = z.number().int().positive();\n break;\n case 'array':\n base = z.array(z.string());\n break;\n case 'string':\n base = length ? z.string().max(length) : z.string();\n break;\n case 'text':\n default:\n base = z.string();\n }\n\n if (nullable) base = (base as any).nullable();\n\n // In strict mode, only required fields stay required; others become optional.\n // In partial mode, everything is optional.\n if (forStrict) {\n return required ? base : base.optional();\n }\n return base.optional();\n}\n\nconst SYSTEM_FIELDS = new Set(['createdAt', 'updatedAt', 'deletedAt']);\n\nfunction resolveFields(modelClass: ModelConstructor): Array<{ name: string; opts: FieldOptions }> {\n const fieldMeta = getFieldMetadata(modelClass) as Record<string, FieldOptions>;\n const hasMeta = Object.keys(fieldMeta).length > 0;\n const fillable = modelClass.fillable;\n\n if (hasMeta) {\n // Exclude primary-key and system-managed fields — users must never write these directly\n let entries = Object.entries(fieldMeta).filter(\n ([name, opts]) => !opts.primary && !SYSTEM_FIELDS.has(name),\n );\n\n // When fillable is defined, restrict validation to only those fields.\n // A field not in fillable (e.g. password set via beforeCreate hook) must not\n // be required from the request body even if it has required: true in @Field().\n if (fillable?.length) {\n entries = entries.filter(([name]) => fillable.includes(name));\n }\n\n return entries.map(([name, opts]) => ({ name, opts }));\n }\n\n // Fallback: fillable defined but no @Field() decorators (e.g. registerTable() without decorators).\n // Column types are unknown — treat all as optional strings and let the DB enforce constraints.\n return (fillable ?? []).map((name) => ({\n name,\n opts: { type: 'string' as FieldType, required: false },\n }));\n}\n\nexport class ValidationGenerator {\n static generateZodSchema<T extends Model>(modelClass: ModelConstructor<T>): z.ZodType<Partial<T>> {\n const fields = resolveFields(modelClass);\n if (fields.length === 0) return z.object({}).partial() as any;\n\n const shape: Record<string, z.ZodTypeAny> = {};\n for (const { name, opts } of fields) {\n shape[name] = zodTypeFor(opts, false);\n }\n return z.object(shape) as any;\n }\n\n static generateStrictZodSchema<T extends Model>(modelClass: ModelConstructor<T>): z.ZodType<any> {\n const fields = resolveFields(modelClass);\n if (fields.length === 0) return z.object({}) as any;\n\n const shape: Record<string, z.ZodTypeAny> = {};\n for (const { name, opts } of fields) {\n shape[name] = zodTypeFor(opts, true);\n }\n return z.object(shape) as any;\n }\n}\n","import {\n pgTable,\n pgSchema,\n text,\n varchar,\n integer,\n doublePrecision,\n boolean,\n timestamp,\n decimal,\n json,\n uuid,\n bigint as pgBigint,\n serial as pgSerial,\n} from 'drizzle-orm/pg-core';\nimport {\n mysqlTable,\n mysqlSchema,\n varchar as mysqlVarchar,\n int,\n double,\n boolean as mysqlBoolean,\n datetime,\n decimal as mysqlDecimal,\n json as mysqlJson,\n text as mysqlText,\n bigint as mysqlBigint,\n mysqlEnum,\n} from 'drizzle-orm/mysql-core';\nimport { getFieldMetadata } from '../decorators/model';\nimport { Dialect, FieldOptions, FieldType } from '../types/model.type';\nimport { ModelConstructor } from './model';\n\nfunction buildPgColumn(name: string, opts: FieldOptions): any {\n const type: FieldType = opts.type;\n\n let col: any;\n switch (type) {\n case 'uuid':\n col = uuid(name);\n break;\n case 'text':\n col = text(name);\n break;\n case 'integer':\n col = integer(name);\n break;\n case 'number':\n col = doublePrecision(name);\n break;\n case 'boolean':\n col = boolean(name);\n break;\n case 'date':\n col = timestamp(name, { mode: 'date' });\n break;\n case 'decimal':\n col = decimal(name, {\n precision: opts.precision ?? 10,\n scale: opts.scale ?? 2,\n });\n break;\n case 'json':\n col = json(name);\n break;\n case 'enum':\n // PostgreSQL: no native column-level enum without pgEnum (a named type).\n // Use text column — Zod validates allowed values at the API layer.\n col = text(name);\n break;\n case 'bigint':\n col = pgBigint(name, { mode: 'number' });\n break;\n case 'serial':\n col = pgSerial(name);\n break;\n case 'array':\n col = text(name).array();\n break;\n case 'string':\n default:\n col = varchar(name, { length: opts.length ?? 255 });\n }\n\n if (opts.primary) col = col.primaryKey();\n // serial columns are implicitly NOT NULL with a default — skip notNull()\n if (opts.required && !opts.nullable && opts.type !== 'serial') col = col.notNull();\n if (opts.unique) col = col.unique();\n if (opts.default !== undefined && opts.type !== 'serial') col = col.default(opts.default);\n\n return col;\n}\n\nfunction buildMysqlColumn(name: string, opts: FieldOptions): any {\n const type: FieldType = opts.type;\n\n let col: any;\n switch (type) {\n case 'uuid':\n col = mysqlVarchar(name, { length: 36 });\n break;\n case 'text':\n col = mysqlText(name);\n break;\n case 'integer':\n col = int(name);\n break;\n case 'number':\n col = double(name);\n break;\n case 'boolean':\n col = mysqlBoolean(name);\n break;\n case 'date':\n col = datetime(name, { mode: 'date' });\n break;\n case 'decimal':\n col = mysqlDecimal(name, {\n precision: opts.precision ?? 10,\n scale: opts.scale ?? 2,\n });\n break;\n case 'json':\n col = mysqlJson(name);\n break;\n case 'enum':\n if (!opts.enumValues?.length) {\n throw new Error(`Field \"${name}\" of type \"enum\" requires the enumValues option`);\n }\n col = mysqlEnum(name, opts.enumValues as [string, ...string[]]);\n break;\n case 'bigint':\n col = mysqlBigint(name, { mode: 'number' });\n break;\n case 'serial':\n col = int(name).autoincrement();\n break;\n case 'array':\n throw new Error(`Field type \"array\" is not supported in MySQL dialect. Use \"json\" instead.`);\n case 'string':\n default:\n col = mysqlVarchar(name, { length: opts.length ?? 255 });\n }\n\n if (opts.primary) col = col.primaryKey();\n if (opts.required && !opts.nullable && opts.type !== 'serial') col = col.notNull();\n if (opts.unique) col = col.unique();\n if (opts.default !== undefined && opts.type !== 'serial') col = col.default(opts.default);\n\n return col;\n}\n\nfunction buildPgColumns(fields: Record<string, FieldOptions>, modelClass: ModelConstructor): Record<string, any> {\n const cols: Record<string, any> = {};\n\n for (const [name, opts] of Object.entries(fields)) {\n cols[name] = buildPgColumn(name, opts);\n }\n\n if (modelClass.timestamps !== false) {\n cols.createdAt = timestamp('createdAt', { mode: 'date' }).defaultNow().notNull();\n cols.updatedAt = timestamp('updatedAt', { mode: 'date' }).defaultNow().notNull();\n }\n\n if (modelClass.softDelete) {\n cols.deletedAt = timestamp('deletedAt', { mode: 'date' });\n }\n\n return cols;\n}\n\nfunction buildMysqlColumns(fields: Record<string, FieldOptions>, modelClass: ModelConstructor): Record<string, any> {\n const cols: Record<string, any> = {};\n\n for (const [name, opts] of Object.entries(fields)) {\n cols[name] = buildMysqlColumn(name, opts);\n }\n\n if (modelClass.timestamps !== false) {\n cols.createdAt = datetime('createdAt', { mode: 'date' }).notNull();\n cols.updatedAt = datetime('updatedAt', { mode: 'date' }).notNull();\n }\n\n if (modelClass.softDelete) {\n cols.deletedAt = datetime('deletedAt', { mode: 'date' });\n }\n\n return cols;\n}\n\nexport class DrizzleTableBuilder {\n static build(modelClass: ModelConstructor, dialect: Dialect): any {\n const fields = getFieldMetadata(modelClass) as Record<string, FieldOptions>;\n const tableName = modelClass.getTableName();\n const schemaName = (modelClass as any).schema as string | undefined;\n\n if (dialect === 'postgresql') {\n const cols = buildPgColumns(fields, modelClass);\n return schemaName\n ? pgSchema(schemaName).table(tableName, cols)\n : pgTable(tableName, cols);\n }\n\n if (dialect === 'mysql') {\n const cols = buildMysqlColumns(fields, modelClass);\n return schemaName\n ? mysqlSchema(schemaName).table(tableName, cols)\n : mysqlTable(tableName, cols);\n }\n\n throw new Error(`Unsupported dialect: ${dialect}. Use 'postgresql' or 'mysql'.`);\n }\n}\n","import http from 'http';\nimport express, { Express } from 'express';\nimport { randomUUID } from 'crypto';\nimport { Crudora } from './crudora';\nimport { Model, ModelConstructor } from './model';\nimport { Dialect } from '../types/model.type';\nimport { CrudoraLogger } from '../types/logger.type';\n\nexport type { CrudoraLogger };\n\n// ─── Rate Limiter ─────────────────────────────────────────────────────────────\n\nexport interface RateLimitConfig {\n /** Sliding-window duration in milliseconds. Default: `60_000` (1 minute). */\n windowMs?: number;\n /** Maximum number of requests per key per window. Default: `100`. */\n max?: number;\n /** Message body returned with 429 responses. Default: `'Too many requests'`. */\n message?: string;\n /**\n * Function that extracts the rate-limit key from a request.\n * Default: `req.ip` (the direct connection IP, or `X-Forwarded-For` if `trust proxy` is set on Express).\n */\n keyGenerator?: (req: any) => string;\n}\n\nfunction createRateLimiter(config: Required<RateLimitConfig>): (req: any, res: any, next: any) => void {\n // Per-key sliding window: key → array of hit timestamps\n const store = new Map<string, number[]>();\n\n // Sweep expired entries once per window so the Map doesn't grow unboundedly\n const timer = setInterval(() => {\n const cutoff = Date.now() - config.windowMs;\n for (const [key, hits] of store.entries()) {\n const active = hits.filter((t) => t > cutoff);\n if (active.length === 0) store.delete(key);\n else store.set(key, active);\n }\n }, config.windowMs);\n // Don't prevent the process from exiting naturally\n if (timer.unref) timer.unref();\n\n return (req: any, res: any, next: any) => {\n const key = config.keyGenerator(req);\n const now = Date.now();\n const cutoff = now - config.windowMs;\n\n const hits = (store.get(key) ?? []).filter((t) => t > cutoff);\n const remaining = Math.max(0, config.max - hits.length - 1);\n const resetAt = Math.ceil((now + config.windowMs) / 1000);\n\n res.setHeader('X-RateLimit-Limit', config.max);\n res.setHeader('X-RateLimit-Remaining', remaining);\n res.setHeader('X-RateLimit-Reset', resetAt);\n\n if (hits.length >= config.max) {\n res.setHeader('Retry-After', Math.ceil(config.windowMs / 1000));\n return res.status(429).json({\n success: false,\n error: { code: 'RATE_LIMIT_EXCEEDED', message: config.message },\n });\n }\n\n hits.push(now);\n store.set(key, hits);\n next();\n };\n}\n\n// ─── Logger ───────────────────────────────────────────────────────────────────\n\nfunction createDefaultLogger(): CrudoraLogger {\n const fmt = (level: string, msg: string, ctx?: Record<string, any>) =>\n JSON.stringify({ level, time: new Date().toISOString(), msg, ...ctx });\n return {\n error: (msg, ctx) => console.error(fmt('error', msg, ctx)),\n warn: (msg, ctx) => console.warn(fmt('warn', msg, ctx)),\n info: (msg, ctx) => console.info(fmt('info', msg, ctx)),\n debug: (msg, ctx) => console.debug(fmt('debug', msg, ctx)),\n };\n}\n\n// ─── Config ───────────────────────────────────────────────────────────────────\n\nexport interface CrudoraServerConfig {\n port?: number;\n /**\n * CORS configuration.\n * - `true` (default): allow all origins (`*`)\n * - `false`: disable CORS headers entirely\n * - `string`: allow a single specific origin, e.g. `'https://app.example.com'`\n * - `string[]`: allow a list of origins; the request's Origin is reflected if it matches\n */\n cors?: boolean | string | string[];\n bodyParser?: boolean;\n /**\n * Maximum request body size accepted by the JSON and URL-encoded body parsers.\n * Accepts a number (bytes) or a string with a unit suffix (`'100kb'`, `'5mb'`).\n * Default: `'100kb'`.\n */\n bodyParserLimit?: string | number;\n db: any;\n dialect: Dialect;\n basePath?: string;\n /**\n * Logger for request errors and lifecycle events.\n * - Omit (default): structured JSON written to console (compatible with log aggregators).\n * - Pass a pino/winston instance or any object with `error`, `warn`, `info`, `debug` methods.\n * - Pass `false` to disable all Crudora logging.\n */\n logger?: CrudoraLogger | false;\n /**\n * Built-in sliding-window rate limiter applied to every route.\n * - Omit / `undefined` (default): enabled with 100 requests per minute per IP.\n * - Pass a `RateLimitConfig` object to customise the window, limit, or key function.\n * - Pass `false` to disable rate limiting entirely (e.g. when using an external proxy-level limiter).\n *\n * **Important:** This limiter is in-memory and per-process. In multi-instance deployments\n * (load balancer, Kubernetes replicas), each instance tracks its own counter independently —\n * the effective limit per client is `max × instanceCount`. Use a Redis-backed limiter\n * (e.g. `rate-limiter-flexible`) and pass `rateLimit: false` to disable this one.\n */\n rateLimit?: RateLimitConfig | false;\n /**\n * Socket-level request timeout in milliseconds.\n * Requests that exceed this duration are terminated with a `503` response.\n * - Omit / `0` (default): no timeout.\n * - Recommended: `30_000` (30 s) for most APIs.\n */\n timeout?: number;\n /**\n * Built-in health check endpoint.\n * - `true` (default): mounts `GET /health` returning `{ status: 'ok' }`.\n * - `string`: custom path, e.g. `'/healthz'`.\n * - `false`: disable entirely.\n */\n healthCheck?: boolean | string;\n}\n\ntype ResolvedConfig = Required<Omit<CrudoraServerConfig, 'logger' | 'rateLimit'>> & {\n logger: CrudoraLogger | false;\n rateLimit: Required<RateLimitConfig> | false;\n timeout: number;\n healthCheck: boolean | string;\n};\n\n// ─── Server ───────────────────────────────────────────────────────────────────\n\nexport class CrudoraServer {\n private app: Express;\n private crudora: Crudora;\n private config: ResolvedConfig;\n private httpServer: http.Server | null = null;\n\n constructor(config: CrudoraServerConfig) {\n const resolvedLogger: CrudoraLogger | false =\n config.logger === undefined ? createDefaultLogger() : config.logger;\n\n const resolvedRateLimit: Required<RateLimitConfig> | false =\n config.rateLimit === false\n ? false\n : {\n windowMs: config.rateLimit?.windowMs ?? 60_000,\n max: config.rateLimit?.max ?? 100,\n message: config.rateLimit?.message ?? 'Too many requests',\n keyGenerator: config.rateLimit?.keyGenerator ?? ((req: any) => String(req.ip ?? 'unknown')),\n };\n\n this.config = {\n port: 3000,\n cors: true,\n bodyParser: true,\n bodyParserLimit: '100kb',\n basePath: '/api',\n timeout: 0,\n healthCheck: true,\n ...config,\n logger: resolvedLogger,\n rateLimit: resolvedRateLimit,\n };\n this.app = express();\n this.crudora = new Crudora(\n config.db,\n config.dialect,\n resolvedLogger === false ? undefined : resolvedLogger,\n );\n this.setupMiddleware();\n }\n\n private setupMiddleware(): void {\n // Security headers — applied unconditionally on every response\n this.app.use((_req, res, next) => {\n // Prevent MIME-type sniffing (XSS vector for browsers that ignore Content-Type)\n res.setHeader('X-Content-Type-Options', 'nosniff');\n // Disallow embedding in iframes — protects against clickjacking\n res.setHeader('X-Frame-Options', 'DENY');\n // Explicitly disable the legacy XSS auditor — it can itself be abused\n res.setHeader('X-XSS-Protection', '0');\n next();\n });\n\n // Attach a unique correlation ID to every incoming request\n this.app.use((req: any, _res, next) => {\n req.correlationId = randomUUID();\n next();\n });\n\n // Request timeout — sends 503 if the handler hasn't responded within the window.\n // Applied early so it covers body parsing, route handling, and DB queries.\n if (this.config.timeout > 0) {\n const timeoutMs = this.config.timeout;\n this.app.use((_req, res, next) => {\n const timer = setTimeout(() => {\n if (!res.headersSent) {\n res.status(503).json({ success: false, error: { code: 'TIMEOUT', message: 'Request timed out' } });\n }\n }, timeoutMs);\n res.on('finish', () => clearTimeout(timer));\n res.on('close', () => clearTimeout(timer));\n next();\n });\n }\n\n // Rate limiting — applied before body parsing so abusive requests are rejected\n // before we spend CPU deserializing their body\n if (this.config.rateLimit !== false) {\n this.app.use(createRateLimiter(this.config.rateLimit));\n }\n\n if (this.config.bodyParser) {\n this.app.use(express.json({ limit: this.config.bodyParserLimit }));\n this.app.use(express.urlencoded({ extended: true, limit: this.config.bodyParserLimit }));\n }\n\n if (this.config.cors !== false) {\n this.app.use((req, res, next) => {\n const cors = this.config.cors;\n if (cors === true || cors === undefined) {\n res.header('Access-Control-Allow-Origin', '*');\n } else if (typeof cors === 'string') {\n res.header('Access-Control-Allow-Origin', cors);\n res.header('Vary', 'Origin');\n } else if (Array.isArray(cors)) {\n const requestOrigin = req.headers.origin;\n if (requestOrigin && cors.includes(requestOrigin)) {\n res.header('Access-Control-Allow-Origin', requestOrigin);\n res.header('Vary', 'Origin');\n }\n }\n res.header('Access-Control-Allow-Methods', 'GET,PUT,PATCH,POST,DELETE,OPTIONS');\n res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n if (req.method === 'OPTIONS') {\n res.sendStatus(204);\n } else {\n next();\n }\n });\n }\n }\n\n registerModel(...modelClasses: ModelConstructor[]): this {\n this.crudora.registerModel(...modelClasses);\n return this;\n }\n\n registerTable<T extends Model>(modelClass: ModelConstructor<T>, table: any): this {\n this.crudora.registerTable(modelClass, table);\n return this;\n }\n\n generateRoutes(): this {\n if (this.config.healthCheck !== false) {\n const healthPath = typeof this.config.healthCheck === 'string'\n ? this.config.healthCheck\n : '/health';\n this.app.get(healthPath, (_req, res) => {\n res.json({ success: true, data: { status: 'ok', timestamp: new Date().toISOString() } });\n });\n }\n this.crudora.generateRoutes(this.app, this.config.basePath);\n return this;\n }\n\n use(middleware: any): this {\n this.app.use(middleware);\n return this;\n }\n\n /**\n * Starts the HTTP server and returns the underlying `http.Server` instance.\n * Use the returned server for graceful shutdown:\n *\n * @example\n * const httpServer = server.listen();\n * process.on('SIGTERM', () => httpServer.close(() => process.exit(0)));\n */\n listen(callback?: () => void): http.Server {\n this.httpServer = http.createServer(this.app);\n this.httpServer.listen(this.config.port, () => {\n console.log(`🚀 Crudora server running on port ${this.config.port}`);\n console.log(`📚 API available at http://localhost:${this.config.port}${this.config.basePath}`);\n if (callback) callback();\n });\n return this.httpServer;\n }\n\n /**\n * Returns the `http.Server` instance after `listen()` has been called, or `null` before.\n * Useful when you need the server reference without calling listen again.\n */\n getHttpServer(): http.Server | null {\n return this.httpServer;\n }\n\n getApp(): Express {\n return this.app;\n }\n\n getCrudora(): Crudora {\n return this.crudora;\n }\n\n /**\n * Returns the Drizzle table object for a registered model — delegates to `Crudora.getTable()`.\n * Use this when you need raw DB access to columns excluded by `static hidden`\n * (e.g. a login route that must read the password hash).\n *\n * @example\n * const usersTable = server.getTable(User);\n * const [row] = await db.select().from(usersTable).where(eq(usersTable.email, email)).limit(1);\n */\n getTable<T extends Model>(modelClass: ModelConstructor<T>): any {\n return this.crudora.getTable(modelClass);\n }\n\n get(path: string, ...handlers: Array<(req: any, res: any, next?: any) => void>): this {\n this.crudora.get(path, ...handlers);\n return this;\n }\n\n post(path: string, ...handlers: Array<(req: any, res: any, next?: any) => void>): this {\n this.crudora.post(path, ...handlers);\n return this;\n }\n\n put(path: string, ...handlers: Array<(req: any, res: any, next?: any) => void>): this {\n this.crudora.put(path, ...handlers);\n return this;\n }\n\n delete(path: string, ...handlers: Array<(req: any, res: any, next?: any) => void>): this {\n this.crudora.delete(path, ...handlers);\n return this;\n }\n\n patch(path: string, ...handlers: Array<(req: any, res: any, next?: any) => void>): this {\n this.crudora.patch(path, ...handlers);\n return this;\n }\n}\n","/**\n * Base class for all Crudora models. Extend this to define your table schema,\n * configure lifecycle hooks, and control API behaviour via static properties.\n *\n * Use `@Field()` decorators on instance properties to describe columns.\n * Use `@HasMany()`, `@HasOne()`, `@BelongsTo()`, `@BelongsToMany()` for relations.\n *\n * This is a plain class — **not** a decorator. Extend it:\n * ```ts\n * class User extends Model {\n * static tableName = 'users';\n * }\n * ```\n */\nexport abstract class Model {\n static tableName?: string;\n static primaryKey?: string = 'id';\n static timestamps?: boolean = true;\n static softDelete?: boolean = false;\n static fillable?: string[];\n static hidden?: string[];\n static schema?: string;\n\n static getTableName(): string {\n return this.tableName || this.name.toLowerCase() + 's';\n }\n\n static getPrimaryKey(): string {\n return this.primaryKey || 'id';\n }\n\n // Lifecycle Hooks\n static async beforeCreate?(_data: any): Promise<any> {\n return _data;\n }\n\n static async afterCreate?(_data: any, result: any): Promise<any> {\n return result;\n }\n\n static async afterCreateMany?(_records: any[]): Promise<any[]> {\n return _records;\n }\n\n static async beforeUpdate?(_id: string, _data: any): Promise<any> {\n return _data;\n }\n\n static async afterUpdate?(_id: string, _data: any, result: any): Promise<any> {\n return result;\n }\n\n static async beforeDelete?(_id: string): Promise<void> {\n // Default implementation - do nothing\n }\n\n static async afterDelete?(_id: string, result: any): Promise<any> {\n return result;\n }\n\n static async beforeFind?(options?: any): Promise<any> {\n return options;\n }\n\n static async afterFind?(results: any[]): Promise<any[]> {\n return results;\n }\n\n async beforeSave?(): Promise<void> {\n // Default implementation - do nothing\n }\n\n async afterSave?(): Promise<void> {\n // Default implementation - do nothing\n }\n}\n\nexport type ModelConstructor<T extends Model = Model> = {\n new (): T;\n tableName?: string;\n primaryKey?: string;\n timestamps?: boolean;\n softDelete?: boolean;\n fillable?: string[];\n hidden?: string[];\n schema?: string;\n getTableName(): string;\n getPrimaryKey(): string;\n\n beforeCreate?(data: any): Promise<any>;\n afterCreate?(data: any, result: any): Promise<any>;\n afterCreateMany?(records: any[]): Promise<any[]>;\n beforeUpdate?(id: string, data: any): Promise<any>;\n afterUpdate?(id: string, data: any, result: any): Promise<any>;\n beforeDelete?(id: string): Promise<void>;\n afterDelete?(id: string, result: any): Promise<any>;\n beforeFind?(options?: any): Promise<any>;\n afterFind?(results: any[]): Promise<any[]>;\n} & typeof Model;\n"],"mappings":"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","names":["import_reflect_metadata","import_zod","finalData","drizzleCount","SYSTEM_FIELDS","pgBigint","pgSerial","mysqlVarchar","mysqlText","mysqlBoolean","mysqlDecimal","mysqlJson","mysqlBigint","MAX_RELATIONS","SAFE_KEY_RE","import_crypto","express","http"]}
|