Fix: remove db.server dependency for prisma from trigger

This commit is contained in:
Harshith Mullapudi 2025-08-21 18:42:09 +05:30
parent 6b243b3797
commit d9d39b0318
22 changed files with 155 additions and 116 deletions

View File

@ -1,9 +1,11 @@
import { type ActionFunctionArgs, type LoaderFunctionArgs, json } from "@remix-run/node";
import { PrismaClient } from "@prisma/client";
import {
type ActionFunctionArgs,
type LoaderFunctionArgs,
json,
} from "@remix-run/node";
import { requireAuth } from "~/utils/auth-helper";
import crypto from "crypto";
const prisma = new PrismaClient();
import { prisma } from "~/db.server";
// GET /api/oauth/clients/:clientId - Get specific OAuth client
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
@ -27,7 +29,7 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => {
}
const client = await prisma.oAuthClient.findFirst({
where: {
where: {
id: clientId,
workspaceId: userRecord.Workspace.id,
},
@ -88,7 +90,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
// Verify client exists and belongs to user's workspace
const existingClient = await prisma.oAuthClient.findFirst({
where: {
where: {
id: clientId,
workspaceId: userRecord.Workspace.id,
},
@ -101,16 +103,29 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
// PATCH - Update OAuth client
if (method === "PATCH") {
const body = await request.json();
const { name, description, redirectUris, allowedScopes, requirePkce, logoUrl, homepageUrl, isActive } = body;
const {
name,
description,
redirectUris,
allowedScopes,
requirePkce,
logoUrl,
homepageUrl,
isActive,
} = body;
const updateData: any = {};
if (name !== undefined) updateData.name = name;
if (description !== undefined) updateData.description = description;
if (redirectUris !== undefined) {
updateData.redirectUris = Array.isArray(redirectUris) ? redirectUris.join(',') : redirectUris;
updateData.redirectUris = Array.isArray(redirectUris)
? redirectUris.join(",")
: redirectUris;
}
if (allowedScopes !== undefined) {
updateData.allowedScopes = Array.isArray(allowedScopes) ? allowedScopes.join(',') : allowedScopes;
updateData.allowedScopes = Array.isArray(allowedScopes)
? allowedScopes.join(",")
: allowedScopes;
}
if (requirePkce !== undefined) updateData.requirePkce = requirePkce;
if (logoUrl !== undefined) updateData.logoUrl = logoUrl;
@ -145,7 +160,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
const { action } = body;
if (action === "regenerate_secret") {
const newClientSecret = crypto.randomBytes(32).toString('hex');
const newClientSecret = crypto.randomBytes(32).toString("hex");
const updatedClient = await prisma.oAuthClient.update({
where: { id: clientId },
@ -158,10 +173,11 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
},
});
return json({
success: true,
return json({
success: true,
client: updatedClient,
message: "Client secret regenerated successfully. Save it securely - it won't be shown again."
message:
"Client secret regenerated successfully. Save it securely - it won't be shown again.",
});
}
@ -174,13 +190,15 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
where: { id: clientId },
});
return json({ success: true, message: "OAuth client deleted successfully" });
return json({
success: true,
message: "OAuth client deleted successfully",
});
}
return json({ error: "Method not allowed" }, { status: 405 });
} catch (error) {
console.error("Error managing OAuth client:", error);
return json({ error: "Internal server error" }, { status: 500 });
}
};
};

View File

@ -3,11 +3,9 @@ import {
type LoaderFunctionArgs,
json,
} from "@remix-run/node";
import { PrismaClient } from "@prisma/client";
import { requireAuth } from "~/utils/auth-helper";
import crypto from "crypto";
const prisma = new PrismaClient();
import { prisma } from "~/db.server";
// GET /api/oauth/clients - List OAuth clients for user's workspace
export const loader = async ({ request }: LoaderFunctionArgs) => {
@ -95,7 +93,7 @@ export const action = async ({ request }: ActionFunctionArgs) => {
// Integration scope
"integration",
"integration:read",
"integration:credentials",
"integration:credentials",
"integration:manage",
"integration:webhook",
// MCP scope

View File

@ -4,9 +4,8 @@ import {
type SpaceDeletionResult,
type SpaceAssignmentResult,
} from "@core/types";
import { prisma } from "~/db.server";
import { type Space } from "@prisma/client";
import { logger } from "~/services/logger.service";
import { prisma } from "~/trigger/utils/prisma";
/**
* Create a new space for a user

View File

@ -1,9 +1,7 @@
import { PrismaClient } from "@prisma/client";
import crypto from "crypto";
import { env } from "~/env.server";
import { type JWTPayload, jwtVerify, SignJWT } from "jose";
const prisma = new PrismaClient();
import { prisma } from "~/db.server";
export interface OAuth2AuthorizeRequest {
client_id: string;

View File

@ -5,7 +5,7 @@ import {
type UpdateSpaceParams,
type SpaceAssignmentResult,
} from "@core/types";
import { prisma } from "~/db.server";
import { type Space } from "@prisma/client";
import { triggerSpaceAssignment } from "~/trigger/spaces/space-assignment";
import {
@ -18,7 +18,7 @@ import {
removeStatementsFromSpace,
updateSpace,
} from "./graphModels/space";
import { type Space } from "@prisma/client";
import { prisma } from "~/trigger/utils/prisma";
export class SpaceService {
/**

View File

@ -1,10 +1,9 @@
import { PrismaClient } from "@prisma/client";
import { LLMMappings } from "@core/types";
import { logger, task } from "@trigger.dev/sdk/v3";
import { generate } from "../chat/stream-utils";
import { conversationTitlePrompt } from "./prompt";
import { prisma } from "../utils/prisma";
const prisma = new PrismaClient();
export const createConversationTitle = task({
id: "create-conversation-title",
run: async (payload: { conversationId: string; message: string }) => {

View File

@ -1,13 +1,11 @@
import { queue, task } from "@trigger.dev/sdk";
import { z } from "zod";
import { KnowledgeGraphService } from "~/services/knowledgeGraph.server";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
import { IngestionStatus } from "@core/database";
import { logger } from "~/services/logger.service";
import { triggerSpaceAssignment } from "../spaces/space-assignment";
import { prisma } from "../utils/prisma";
export const IngestBodyRequest = z.object({
episodeBody: z.string(),

View File

@ -1,10 +1,8 @@
import { PrismaClient } from "@prisma/client";
import { IntegrationEventType } from "@core/types";
import { logger, schedules, tasks } from "@trigger.dev/sdk/v3";
import { type integrationRun } from "./integration-run";
const prisma = new PrismaClient();
import { prisma } from "../utils/prisma";
export const integrationRunSchedule = schedules.task({
id: "integration-run-schedule",

View File

@ -1,9 +1,7 @@
import { PrismaClient } from "@prisma/client";
import { logger, schedules, task } from "@trigger.dev/sdk/v3";
import { integrationRunSchedule } from "./integration-run-schedule";
const prisma = new PrismaClient();
import { prisma } from "../utils/prisma";
export const scheduler = task({
id: "scheduler",

View File

@ -12,7 +12,10 @@ import {
} from "~/services/graphModels/space";
import { triggerSpaceSummary } from "./space-summary";
import { triggerSpacePattern } from "./space-pattern";
import { updateMultipleSpaceStatuses, SPACE_STATUS } from "../utils/space-status";
import {
updateMultipleSpaceStatuses,
SPACE_STATUS,
} from "../utils/space-status";
import type { CoreMessage } from "ai";
import { z } from "zod";
import { type Space } from "@prisma/client";
@ -321,7 +324,7 @@ export const spaceAssignmentTask = task({
userId,
operation: "space-assignment",
metadata: { mode, phase: "start_processing" },
}
},
);
} catch (statusError) {
logger.warn(`Failed to update space statuses to processing:`, {
@ -332,7 +335,7 @@ export const spaceAssignmentTask = task({
}
}
// 5. Trigger space summaries for affected spaces (fan-out pattern)
// 5. Trigger space summaries for affected spaces (fan-out pattern)
if (affectedSpaces.size > 0) {
try {
logger.info(
@ -415,7 +418,7 @@ export const spaceAssignmentTask = task({
userId,
operation: "space-assignment",
metadata: { mode, phase: "completed_processing" },
}
},
);
} catch (finalStatusError) {
logger.warn(`Failed to update space statuses to ready:`, {

View File

@ -4,20 +4,25 @@ import { makeModelCall } from "~/lib/model.server";
import { runQuery } from "~/lib/neo4j.server";
import type { CoreMessage } from "ai";
import { z } from "zod";
import { prisma } from "~/db.server";
import {
EXPLICIT_PATTERN_TYPES,
IMPLICIT_PATTERN_TYPES,
type SpacePattern,
type PatternDetectionResult,
type UserConfirmationStatus,
} from "@core/types";
import { createSpacePattern, getSpace } from "../utils/space-utils";
interface SpacePatternPayload {
userId: string;
workspaceId: string;
spaceId: string;
triggerSource?: "summary_complete" | "manual" | "scheduled" | "new_space" | "growth_threshold" | "ingestion_complete";
triggerSource?:
| "summary_complete"
| "manual"
| "scheduled"
| "new_space"
| "growth_threshold"
| "ingestion_complete";
}
interface SpaceStatementData {
@ -78,7 +83,7 @@ export const spacePatternTask = task({
try {
// Get space data and check if it has enough content
const space = await getSpaceForPatternAnalysis(spaceId, userId);
const space = await getSpaceForPatternAnalysis(spaceId);
if (!space) {
return {
success: false,
@ -155,17 +160,9 @@ export const spacePatternTask = task({
async function getSpaceForPatternAnalysis(
spaceId: string,
userId: string,
): Promise<SpaceThemeData | null> {
try {
const space = await prisma.space.findFirst({
where: {
id: spaceId,
workspace: {
userId: userId,
},
},
});
const space = await getSpace(spaceId);
if (!space || !space.themes || space.themes.length === 0) {
logger.warn(
@ -536,13 +533,7 @@ async function storePatterns(
if (allPatterns.length === 0) return;
// Store in PostgreSQL
await prisma.spacePattern.createMany({
data: allPatterns.map((pattern) => ({
...pattern,
spaceId,
userConfirmed: pattern.userConfirmed as any, // Temporary cast until Prisma client is regenerated
})),
});
await createSpacePattern(spaceId, allPatterns);
logger.info(`Stored ${allPatterns.length} patterns`, {
explicit: explicitPatterns.length,

View File

@ -6,8 +6,8 @@ import { runQuery } from "~/lib/neo4j.server";
import { updateSpaceStatus, SPACE_STATUS } from "../utils/space-status";
import type { CoreMessage } from "ai";
import { z } from "zod";
import { prisma } from "~/db.server";
import { spacePatternTask, triggerSpacePattern } from "./space-pattern";
import { triggerSpacePattern } from "./space-pattern";
import { getSpace, updateSpace } from "../utils/space-utils";
interface SpaceSummaryPayload {
userId: string;
@ -90,8 +90,8 @@ export const spaceSummaryTask = task({
await updateSpaceStatus(spaceId, SPACE_STATUS.READY, {
userId,
operation: "space-summary",
metadata: {
triggerSource,
metadata: {
triggerSource,
phase: "completed_summary",
statementCount: summaryResult.statementCount,
confidence: summaryResult.confidence,
@ -129,7 +129,11 @@ export const spaceSummaryTask = task({
await updateSpaceStatus(spaceId, SPACE_STATUS.ERROR, {
userId,
operation: "space-summary",
metadata: { triggerSource, phase: "failed_summary", error: "Failed to generate summary" },
metadata: {
triggerSource,
phase: "failed_summary",
error: "Failed to generate summary",
},
});
logger.warn(`Failed to generate summary for space ${spaceId}`);
@ -146,10 +150,10 @@ export const spaceSummaryTask = task({
await updateSpaceStatus(spaceId, SPACE_STATUS.ERROR, {
userId,
operation: "space-summary",
metadata: {
triggerSource,
phase: "exception",
error: error instanceof Error ? error.message : "Unknown error"
metadata: {
triggerSource,
phase: "exception",
error: error instanceof Error ? error.message : "Unknown error",
},
});
} catch (statusError) {
@ -483,9 +487,7 @@ async function getExistingSummary(spaceId: string): Promise<{
lastUpdated: Date;
} | null> {
try {
const existingSummary = await prisma.space.findUnique({
where: { id: spaceId },
});
const existingSummary = await getSpace(spaceId);
if (existingSummary?.summary) {
return {
@ -616,16 +618,7 @@ function parseSummaryResponse(response: string): {
async function storeSummary(summaryData: SpaceSummaryData): Promise<void> {
try {
// Store in PostgreSQL for API access and persistence
await prisma.space.update({
where: {
id: summaryData.spaceId,
},
data: {
summary: summaryData.summary,
themes: summaryData.themes,
statementCount: summaryData.statementCount,
},
});
await updateSpace(summaryData);
// Also store in Neo4j for graph-based queries
const query = `

View File

@ -6,8 +6,7 @@ import * as path from "path";
import { type MCPTool } from "./types";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
import { prisma } from "./prisma";
export const configureStdioMCPEnvironment = (
spec: any,

View File

@ -1,10 +1,8 @@
import { PrismaClient } from "@prisma/client";
import { type Message } from "@core/types";
import { addToQueue } from "./queue";
import { triggerWebhookDelivery } from "../webhooks/webhook-delivery";
import { logger } from "@trigger.dev/sdk";
const prisma = new PrismaClient();
import { prisma } from "./prisma";
export const createIntegrationAccount = async ({
integrationDefinitionId,

View File

@ -0,0 +1,10 @@
import { PrismaClient } from "@prisma/client";
import { singleton } from "~/utils/singleton";
export const prisma = singleton("prisma", getClient);
function getClient() {
const client = new PrismaClient();
return client;
}

View File

@ -1,8 +1,7 @@
import { IngestionStatus, PrismaClient } from "@prisma/client";
import { type z } from "zod";
import { type IngestBodyRequest, ingestTask } from "../ingest/ingest";
const prisma = new PrismaClient();
import { prisma } from "./prisma";
export const addToQueue = async (
body: z.infer<typeof IngestBodyRequest>,

View File

@ -1,5 +1,5 @@
import { prisma } from "~/db.server";
import { logger } from "~/services/logger.service";
import { prisma } from "./prisma";
/**
* Update space status with proper error handling and logging
@ -11,14 +11,14 @@ export async function updateSpaceStatus(
userId?: string;
operation?: string;
metadata?: Record<string, unknown>;
}
},
): Promise<void> {
try {
await prisma.space.update({
where: { id: spaceId },
data: { status },
});
logger.info(`Updated space status`, {
spaceId,
status,
@ -48,7 +48,7 @@ export async function updateMultipleSpaceStatuses(
userId?: string;
operation?: string;
metadata?: Record<string, unknown>;
}
},
): Promise<void> {
if (spaceIds.length === 0) return;
@ -80,7 +80,7 @@ export async function updateMultipleSpaceStatuses(
});
await Promise.allSettled(updatePromises);
logger.info(`Completed batch status update`, {
status,
totalSpaces: spaceIds.length,
@ -109,4 +109,4 @@ export const SPACE_STATUS = {
PENDING: "pending",
} as const;
export type SpaceStatus = typeof SPACE_STATUS[keyof typeof SPACE_STATUS];
export type SpaceStatus = (typeof SPACE_STATUS)[keyof typeof SPACE_STATUS];

View File

@ -0,0 +1,46 @@
import { type SpacePattern } from "@core/types";
import { prisma } from "./prisma";
export const getSpace = async (spaceId: string) => {
const space = await prisma.space.findFirst({
where: {
id: spaceId,
},
});
return space;
};
export const createSpacePattern = async (
spaceId: string,
allPatterns: Omit<
SpacePattern,
"id" | "createdAt" | "updatedAt" | "spaceId"
>[],
) => {
return await prisma.spacePattern.createMany({
data: allPatterns.map((pattern) => ({
...pattern,
spaceId,
userConfirmed: pattern.userConfirmed as any, // Temporary cast until Prisma client is regenerated
})),
});
};
export const updateSpace = async (summaryData: {
spaceId: string;
summary: string;
themes: string[];
statementCount: number;
}) => {
return await prisma.space.update({
where: {
id: summaryData.spaceId,
},
data: {
summary: summaryData.summary,
themes: summaryData.themes,
statementCount: summaryData.statementCount,
},
});
};

View File

@ -4,7 +4,6 @@ import {
type ConversationHistory,
type IntegrationDefinitionV2,
type Prisma,
PrismaClient,
UserType,
type UserUsage,
type Workspace,
@ -22,8 +21,7 @@ import axios from "axios";
import nodeCrypto from "node:crypto";
import { customAlphabet, nanoid } from "nanoid";
import { Exa } from "exa-js";
const prisma = new PrismaClient();
import { prisma } from "./prisma";
// Token generation utilities
const tokenValueLength = 40;

View File

@ -1,13 +1,11 @@
import { queue, task } from "@trigger.dev/sdk";
import { PrismaClient } from "@prisma/client";
import { logger } from "~/services/logger.service";
import {
deliverWebhook,
type WebhookEventType,
type WebhookTarget,
} from "./webhook-delivery-utils";
const prisma = new PrismaClient();
import { prisma } from "../utils/prisma";
const integrationWebhookQueue = queue({
name: "integration-webhook-queue",

View File

@ -1,13 +1,11 @@
import { queue, task } from "@trigger.dev/sdk";
import { PrismaClient } from "@prisma/client";
import { logger } from "~/services/logger.service";
import { WebhookDeliveryStatus } from "@core/database";
import {
deliverWebhook,
prepareWebhookTargets,
} from "./webhook-delivery-utils";
const prisma = new PrismaClient();
import { prisma } from "../utils/prisma";
const webhookQueue = queue({
name: "webhook-delivery-queue",

View File

@ -27,16 +27,16 @@ export default defineConfig({
build: {
extensions: [
syncEnvVars(() => ({
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY as string,
API_BASE_URL: process.env.API_BASE_URL as string,
DATABASE_URL: process.env.DATABASE_URL as string,
EMBEDDING_MODEL: process.env.EMBEDDING_MODEL as string,
ENCRYPTION_KEY: process.env.ENCRYPTION_KEY as string,
MODEL: process.env.MODEL ?? "gpt-4.1-2025-04-14",
NEO4J_PASSWORD: process.env.NEO4J_PASSWORD as string,
NEO4J_URI: process.env.NEO4J_URI as string,
NEO4J_USERNAME: process.env.NEO4J_USERNAME as string,
OPENAI_API_KEY: process.env.OPENAI_API_KEY as string,
// ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY as string,
// API_BASE_URL: process.env.API_BASE_URL as string,
// DATABASE_URL: process.env.DATABASE_URL as string,
// EMBEDDING_MODEL: process.env.EMBEDDING_MODEL as string,
// ENCRYPTION_KEY: process.env.ENCRYPTION_KEY as string,
// MODEL: process.env.MODEL ?? "gpt-4.1-2025-04-14",
// NEO4J_PASSWORD: process.env.NEO4J_PASSWORD as string,
// NEO4J_URI: process.env.NEO4J_URI as string,
// NEO4J_USERNAME: process.env.NEO4J_USERNAME as string,
// OPENAI_API_KEY: process.env.OPENAI_API_KEY as string,
})),
prismaExtension({
schema: "prisma/schema.prisma",