refactor: extract provider logic into modular registry

Each AI provider now has its own module implementing a ProviderModule
interface with createGateway, getAuthHeaders, and fetchModels methods.
This replaces the monolithic switch statements in ai-provider.ts and
models.post.ts with a clean registry pattern.
This commit is contained in:
Zoe
2026-04-27 12:04:49 -05:00
parent 6ca4de4cab
commit 1d40812f2a
21 changed files with 1221 additions and 798 deletions
+44 -19
View File
@@ -1,13 +1,16 @@
import { nanoid } from "nanoid";
import { Providers } from "~/types/model";
import { db } from "~~/server/lib/db";
import { providers as providersSchema } from "~~/drizzle/schema";
import { eq } from "drizzle-orm";
import { getAllProviders, getProviderBaseUrl } from "~~/server/utils/providers";
export default defineEventHandler(async (event) => {
await protectRoute(event);
const userId = event.context.user!.id as string;
const providers = await db.query.providers.findMany({
const providerIds = getAllProviders().map(p => p.id);
let providers = await db.query.providers.findMany({
where: {
userId,
},
@@ -16,24 +19,46 @@ export default defineEventHandler(async (event) => {
},
});
Providers.forEach(async p => {
const createPromises: Promise<any>[] = [];
providerIds.forEach(p => {
if (!providers.find(provider => provider.type === p)) {
const [created] = await db.insert(providersSchema).values({
id: nanoid(),
userId,
type: p,
name: p,
enabled: false,
config: {},
createdAt: new Date(),
updatedAt: new Date(),
}).returning() as typeof providers;
if (created) {
created.models = [];
providers.push(created);
}
createPromises.push(
db.insert(providersSchema).values({
id: nanoid(),
userId,
type: p,
name: p,
enabled: false,
config: {},
createdAt: new Date(),
updatedAt: new Date(),
}).returning() as any
);
}
});
return providers;
})
const createdResults = await Promise.all(createPromises);
for (const created of createdResults) {
if (created && created[0]) {
created[0].models = [];
providers.push(created[0]);
}
}
const deletePromises: Promise<any>[] = [];
providers.forEach(provider => {
if (!providerIds.includes(provider.type)) {
deletePromises.push(db.delete(providersSchema).where(eq(providersSchema.id, provider.id)));
providers = providers.filter(p => p.id !== provider.id);
}
});
await Promise.all(deletePromises);
const enrichedProviders = providers.map(p => ({
...p,
defaultBaseUrl: getProviderBaseUrl(p.type),
}));
return enrichedProviders;
});