From 758472bd5c46b29c143f754debd1cfddee5606b9 Mon Sep 17 00:00:00 2001 From: kevin olson Date: Tue, 9 Sep 2025 02:10:20 -0500 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20handle=20pluralization?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/runtime/server/utils/binder.ts | 52 ++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/runtime/server/utils/binder.ts b/src/runtime/server/utils/binder.ts index 7b74d2c..cdf11e2 100644 --- a/src/runtime/server/utils/binder.ts +++ b/src/runtime/server/utils/binder.ts @@ -4,12 +4,60 @@ import { createError, defineEventHandler } from 'h3' import type { BinderConfig } from '#api-utils' export function modelBinder(config: BinderConfig, router: Router) { + function findTableName(modelName: string, schema: Record): string | null { + const variations = [] + + // Enhanced pluralization rules + if (modelName.endsWith('s') || modelName.endsWith('x') || modelName.endsWith('z') + || modelName.endsWith('ch') || modelName.endsWith('sh')) { + // Sibilants: add "es" (e.g., kiss -> kisses, box -> boxes, church -> churches) + variations.push(`${modelName}es`) + } + else if (modelName.endsWith('y') && modelName.length > 1 + && !'aeiou'.includes(modelName[modelName.length - 2])) { + // Consonant + y: change y to ies (e.g., city -> cities, baby -> babies) + variations.push(`${modelName.slice(0, -1)}ies`) + } + else if (modelName.endsWith('f')) { + // f -> ves (e.g., leaf -> leaves, wolf -> wolves) + variations.push(`${modelName.slice(0, -1)}ves`) + } + else if (modelName.endsWith('fe')) { + // fe -> ves (e.g., knife -> knives, life -> lives) + variations.push(`${modelName.slice(0, -2)}ves`) + } + else if (modelName.endsWith('o') && modelName.length > 1 + && !'aeiou'.includes(modelName[modelName.length - 2])) { + // Consonant + o: add "es" (e.g., hero -> heroes, potato -> potatoes) + variations.push(`${modelName}es`) + } + + // Always try standard pluralization as fallback + variations.push(`${modelName}s`) + + // Try original name (for words that don't pluralize or are already plural) + variations.push(modelName) + + for (const variation of variations) { + if (schema[variation]) { + return variation + } + } + + return null + } + async function lookupModels>(modelNames: (keyof T)[], event: H3Event): Promise { const db = config.drizzleFactory() const result = {} as T + console.log('modelNames', modelNames) for (const key of modelNames) { - const table = db.session.schema.schema[`${String(key)}s` as keyof typeof db.session.schema.schema] + const tableName = findTableName(String(key), db.session.schema.schema) + if (!tableName) + throw createError({ statusCode: 404, statusMessage: 'Not Found' }) + + const table = db.session.schema.schema[tableName as keyof typeof db.session.schema.schema] if (!table) throw createError({ statusCode: 404, statusMessage: 'Not Found' }) @@ -17,7 +65,7 @@ export function modelBinder(config: BinderConfig, router: Router) { if (!id) throw createError({ statusCode: 404, statusMessage: 'Not Found' }) - const record = await db.query[`${String(key)}s`].findFirst({ + const record = await db.query[tableName].findFirst({ where: table.columns.id.columnType === 'MySqlBinary' ? eq(table.columns.id, sql`UUID_TO_BIN(${id})`) : eq(table.columns.id, id), From 7064638a9b53c486743ce12f8d67a71a668fae76 Mon Sep 17 00:00:00 2001 From: kevin olson Date: Tue, 9 Sep 2025 02:13:04 -0500 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=9A=A7=20pull=20debug=20info?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/runtime/server/utils/binder.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/runtime/server/utils/binder.ts b/src/runtime/server/utils/binder.ts index cdf11e2..9952da6 100644 --- a/src/runtime/server/utils/binder.ts +++ b/src/runtime/server/utils/binder.ts @@ -51,7 +51,6 @@ export function modelBinder(config: BinderConfig, router: Router) { const db = config.drizzleFactory() const result = {} as T - console.log('modelNames', modelNames) for (const key of modelNames) { const tableName = findTableName(String(key), db.session.schema.schema) if (!tableName)