diff --git a/apps/gateway/src/routes/api/v1/projects/:projectId/commits/:commitUuid/documents/handlers/run.ts b/apps/gateway/src/routes/api/v1/projects/:projectId/commits/:commitUuid/documents/handlers/run.ts index dfeada8f9..10fa33fa1 100644 --- a/apps/gateway/src/routes/api/v1/projects/:projectId/commits/:commitUuid/documents/handlers/run.ts +++ b/apps/gateway/src/routes/api/v1/projects/:projectId/commits/:commitUuid/documents/handlers/run.ts @@ -25,16 +25,13 @@ export const runHandler = factory.createHandlers( async (stream) => { const { projectId, commitUuid } = c.req.param() const { documentPath, parameters, source } = c.req.valid('json') - const workspace = c.get('workspace') - const { document, commit } = await getData({ workspace, projectId: Number(projectId!), commitUuid: commitUuid!, documentPath: documentPath!, }) - const result = await runDocumentAtCommit({ workspace, document, diff --git a/apps/web/src/helpers/captureException.ts b/apps/web/src/helpers/captureException.ts new file mode 100644 index 000000000..ce03e2d3c --- /dev/null +++ b/apps/web/src/helpers/captureException.ts @@ -0,0 +1,10 @@ +import * as Sentry from '@sentry/nextjs' +import env from '$/env' + +export const captureException = (error: Error) => { + if (env.NODE_ENV === 'production') { + Sentry.captureException(error) + } else { + console.error(error) + } +} diff --git a/apps/web/src/services/user/setupService.ts b/apps/web/src/services/user/setupService.ts index 51673d21b..a077bb575 100644 --- a/apps/web/src/services/user/setupService.ts +++ b/apps/web/src/services/user/setupService.ts @@ -4,10 +4,14 @@ import { Result } from '@latitude-data/core/lib/Result' import Transaction, { PromisedResult, } from '@latitude-data/core/lib/Transaction' +import { createApiKey } from '@latitude-data/core/services/apiKeys/create' +import { createMembership } from '@latitude-data/core/services/memberships/create' +import { importDefaultProject } from '@latitude-data/core/services/projects/import' import { createProviderApiKey } from '@latitude-data/core/services/providerApiKeys/create' import { createUser } from '@latitude-data/core/services/users/createUser' import { createWorkspace } from '@latitude-data/core/services/workspaces/create' import { env } from '@latitude-data/env' +import { captureException } from '$/helpers/captureException' export default function setupService({ email, @@ -27,28 +31,41 @@ export default function setupService({ if (userResult.error) return userResult const user = userResult.value - const result = await createWorkspace( + const resultWorkspace = await createWorkspace( { name: companyName, user, }, tx, ) + if (resultWorkspace.error) return resultWorkspace + const workspace = resultWorkspace.value - if (result.error) return result - - const workspace = result.value - const resultProviderApiKey = await createProviderApiKey( - { - workspace, - provider: Providers.OpenAI, - name: env.DEFAULT_PROVIDER_ID, - token: env.DEFAULT_PROVIDER_API_KEY, - authorId: user.id, - }, + const resultImportingDefaultProject = await importDefaultProject( + { workspace, user }, tx, ) - if (resultProviderApiKey.error) return resultProviderApiKey + if (resultImportingDefaultProject.error) { + captureException(resultImportingDefaultProject.error) + } + + const results = await Promise.all([ + createMembership({ confirmedAt: new Date(), user, workspace }, tx), + createApiKey({ workspace }, tx), + createProviderApiKey( + { + workspace, + provider: Providers.OpenAI, + name: env.DEFAULT_PROVIDER_ID, + token: env.DEFAULT_PROVIDER_API_KEY, + authorId: user.id, + }, + tx, + ), + ]) + + const result = Result.findError(results) + if (result) return result return Result.ok({ user, diff --git a/packages/core/src/events/handlers/index.ts b/packages/core/src/events/handlers/index.ts index 781c38870..ebe972fba 100644 --- a/packages/core/src/events/handlers/index.ts +++ b/packages/core/src/events/handlers/index.ts @@ -6,6 +6,7 @@ import { Message, ProviderLog, User, + Workspace, } from '../../browser' import { PartialConfig } from '../../services/ai' import { createEvaluationResultJob } from './createEvaluationResultJob' @@ -91,6 +92,14 @@ export type AIProviderCallCompletedEvent = LatitudeEventGeneric< } > +export type WorkspaceCreatedEvent = LatitudeEventGeneric< + 'workspaceCreated', + { + workspace: Workspace + user: User + } +> + export type LatitudeEvent = | MembershipCreatedEvent | UserCreatedEvent @@ -99,6 +108,7 @@ export type LatitudeEvent = | DocumentRunEvent | ProviderLogCreatedEvent | AIProviderCallCompletedEvent + | WorkspaceCreatedEvent export interface IEventsHandlers { magicLinkTokenCreated: EventHandler[] @@ -108,6 +118,7 @@ export interface IEventsHandlers { documentRun: EventHandler[] providerLogCreated: EventHandler[] aiProviderCallCompleted: EventHandler[] + workspaceCreated: EventHandler[] } export const EventHandlers: IEventsHandlers = { @@ -118,4 +129,5 @@ export const EventHandlers: IEventsHandlers = { documentRun: [createDocumentLogJob], providerLogCreated: [], aiProviderCallCompleted: [], + workspaceCreated: [], } as const diff --git a/packages/core/src/lib/Result.ts b/packages/core/src/lib/Result.ts index b1eb67d36..d374125ac 100644 --- a/packages/core/src/lib/Result.ts +++ b/packages/core/src/lib/Result.ts @@ -55,9 +55,9 @@ export class Result { return result.ok } - public static findError( - results: TypedResult[], - ): TypedResult | undefined { - return results.find((r) => !r.ok) + public static findError( + results: TypedResult[], + ): ErrorResult | undefined { + return results.find((r) => !r.ok) as ErrorResult | undefined } } diff --git a/packages/core/src/services/projects/import.ts b/packages/core/src/services/projects/import.ts index 286f77883..dc9fb5057 100644 --- a/packages/core/src/services/projects/import.ts +++ b/packages/core/src/services/projects/import.ts @@ -36,6 +36,7 @@ export async function importDefaultProject( await defaultProjectDocumentsScope.getDocumentsFromMergedCommits({ projectId: defaultProject!.id, }) + if (defaultDocuments.error) return defaultDocuments return Transaction.call(async (tx) => { diff --git a/packages/core/src/services/workspaces/create.ts b/packages/core/src/services/workspaces/create.ts index 94276fcad..ebfb09a72 100644 --- a/packages/core/src/services/workspaces/create.ts +++ b/packages/core/src/services/workspaces/create.ts @@ -1,10 +1,8 @@ import { User, Workspace } from '../../browser' import { database } from '../../client' +import { publisher } from '../../events/publisher' import { Result, Transaction } from '../../lib' import { workspaces } from '../../schema' -import { createApiKey } from '../apiKeys/create' -import { createMembership } from '../memberships/create' -import { importDefaultProject } from '../projects/import' export async function createWorkspace( { @@ -23,10 +21,10 @@ export async function createWorkspace( .returning() const workspace = insertedWorkspaces[0]! - await createMembership({ confirmedAt: new Date(), user, workspace }, tx) - await createApiKey({ workspace }, tx) - - await importDefaultProject({ workspace, user }, tx) + publisher.publish({ + type: 'workspaceCreated', + data: { workspace, user }, + }) return Result.ok(workspace) }, db)