Skip to content

Commit

Permalink
feature: api fetch prompts by commit and path
Browse files Browse the repository at this point in the history
This commit tweaks queries and implements an example on how to find a
prompt by path and commit uuid. It also removes unnecessary table
documentSnapshots.
  • Loading branch information
geclos committed Jul 19, 2024
1 parent 549805f commit df22a4f
Show file tree
Hide file tree
Showing 52 changed files with 2,420 additions and 519 deletions.
6 changes: 3 additions & 3 deletions apps/api/src/common/Paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ export default {
Base: '/api',
V1: {
Base: '/v1',
Chat: {
Base: '/chat',
Completions: '/completions',
Commits: {
Base: '/commits',
Prompt: '/:commitUuid/*',
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/common/RouteError.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import HttpStatusCodes from '@src/common/HttpStatusCodes'
import HttpStatusCodes from '$src/common/HttpStatusCodes'

/**
* Error with status code and message
Expand Down
6 changes: 4 additions & 2 deletions apps/api/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import EnvVars from '@src/common/EnvVars'
import EnvVars from '$src/common/EnvVars'

import server from './server'

const SERVER_START_MSG = 'Express server started on port: ' + EnvVars.PORT

server.listen(EnvVars.PORT, () => console.info(SERVER_START_MSG))
server.listen(EnvVars.PORT, () => {
console.info(SERVER_START_MSG)
})
2 changes: 1 addition & 1 deletion apps/api/src/middlewares/validate.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Result } from '@latitude-data/core'
import { UnprocessableEntityError } from '@src/common/errors'
import { UnprocessableEntityError } from '$src/common/errors'
import { NextFunction, Request, Response } from 'express'
import { ZodError, ZodSchema } from 'zod'

Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/routes/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Paths from '@src/common/Paths'
import Paths from '$src/common/Paths'
import { Router } from 'express'

import v1Router from './v1'
Expand Down
31 changes: 0 additions & 31 deletions apps/api/src/routes/api/v1/chat/completions.test.ts

This file was deleted.

10 changes: 0 additions & 10 deletions apps/api/src/routes/api/v1/chat/index.ts

This file was deleted.

6 changes: 0 additions & 6 deletions apps/api/src/routes/api/v1/chat/routes.ts

This file was deleted.

10 changes: 10 additions & 0 deletions apps/api/src/routes/api/v1/commits/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Paths from '$src/common/Paths'
import { Router } from 'express'

import { promptRoute } from './routes'

const router = Router()

router.get(Paths.Api.V1.Commits.Prompt, promptRoute)

export default router
39 changes: 39 additions & 0 deletions apps/api/src/routes/api/v1/commits/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { materializeDocumentsAtCommit, Node, toTree } from '@latitude-data/core'
import HttpStatusCodes from '$src/common/HttpStatusCodes'
import { BadRequestError, NotFoundError } from '$core/lib/errors'
import { Request, Response } from 'express'

function findNode({ rootNode, path }: { rootNode: Node; path: string }) {
const pathParts = path.split('/')

let currentNode = rootNode
let currentPart = pathParts.shift()
while (currentPart) {
const child = currentNode.children.find(
// NOTE: sanitaze name before comparing
(child) => child.doc?.name === currentPart,
)
if (!child) return null

currentNode = child
currentPart = pathParts.shift()
}

return currentNode
}

export async function promptRoute(req: Request, res: Response) {
const commitUuid = req.params.commitUuid
const path = req.params[0]
if (!path) throw new BadRequestError('Invalid prompt path')

const result = await materializeDocumentsAtCommit({ commitUuid: commitUuid! })
const rootNode = toTree(result.unwrap())
const node = findNode({ rootNode, path })

if (!node) {
throw new NotFoundError('Prompt not found')
} else {
return res.status(HttpStatusCodes.OK).json(node.doc)
}
}
6 changes: 3 additions & 3 deletions apps/api/src/routes/api/v1/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Paths from '@src/common/Paths'
import Paths from '$src/common/Paths'
import { Router } from 'express'

import chatRouter from './chat'
import commitsRouter from './commits'

const router = Router()

router.use(Paths.Api.V1.Chat.Base, chatRouter)
router.use(Paths.Api.V1.Commits.Base, commitsRouter)

export default router
2 changes: 1 addition & 1 deletion apps/api/src/routes/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Paths from '@src/common/Paths'
import Paths from '$src/common/Paths'
import { Router } from 'express'

import apiRouter from './api'
Expand Down
12 changes: 4 additions & 8 deletions apps/api/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import morgan from 'morgan'

import 'express-async-errors'

import EnvVars from '@src/common/EnvVars'
import HttpStatusCodes from '@src/common/HttpStatusCodes'
import { NodeEnvs } from '@src/common/misc'
import BaseRouter from '@src/routes'
import EnvVars from '$src/common/EnvVars'
import HttpStatusCodes from '$src/common/HttpStatusCodes'
import { NodeEnvs } from '$src/common/misc'
import BaseRouter from '$src/routes'

import { LatitudeError, UnprocessableEntityError } from './common/errors'

Expand All @@ -35,10 +35,6 @@ app.use('/', BaseRouter)

// Add error handler
app.use((err: Error, _: Request, res: Response, __: NextFunction) => {
if (EnvVars.NODE_ENV !== NodeEnvs.Test.valueOf()) {
console.error(err.message, true)
}

if (err instanceof UnprocessableEntityError) {
return res.status(err.statusCode).json({
name: err.name,
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/services/elastic/client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Client } from '@elastic/elasticsearch'
import EnvVars from '@src/common/EnvVars'
import EnvVars from '$src/common/EnvVars'

export default new Client({
node: EnvVars.ELASTIC_URL,
Expand Down
2 changes: 1 addition & 1 deletion apps/api/test/support/Paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Convert paths to full for testing.
*/

import Paths from '@src/common/Paths'
import Paths from '$src/common/Paths'
import jetPaths from 'jet-paths'

export default jetPaths(Paths)
2 changes: 1 addition & 1 deletion apps/api/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"outDir": "dist",
"baseUrl": "./",
"paths": {
"@src/*": ["src/*"],
"$src/*": ["src/*"],
"$core/*": ["../../packages/core/src/*"]
},
"useUnknownInCatchVariables": false
Expand Down
12 changes: 12 additions & 0 deletions apps/web/src/actions/commits/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use server'

import { createCommit } from '@latitude-data/core'

import { withProject } from '../procedures'

export const createCommitAction = withProject
.createServerAction()
.handler(async ({ input }) => {
const result = await createCommit({ projectId: input.projectId })
return result.unwrap()
})
9 changes: 9 additions & 0 deletions apps/web/src/actions/commits/fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use server'

import { listCommits } from '@latitude-data/core'

import { withProject } from '../procedures'

export const getCommitsAction = withProject
.createServerAction()
.handler(() => listCommits())
17 changes: 17 additions & 0 deletions apps/web/src/actions/documents/fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use server'

import { materializeDocumentsAtCommit } from '@latitude-data/core'
import { z } from 'zod'

import { withProject } from '../procedures'

export const getDocumentsAtCommitAction = withProject
.createServerAction()
.input(z.object({ commitUuid: z.string() }))
.handler(async ({ input }) => {
const result = await materializeDocumentsAtCommit({
commitUuid: input.commitUuid,
})

return result.unwrap()
})
13 changes: 7 additions & 6 deletions apps/web/src/actions/procedures/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ export const authProcedure = createServerActionProcedure().handler(async () => {
export const withProject = createServerActionProcedure(authProcedure)
.input(z.object({ projectId: z.number() }))
.handler(async ({ input, ctx }) => {
const project = (
await findProject({
projectId: input.projectId,
workspaceId: ctx.workspace.id,
})
).unwrap()
const res = await findProject({
projectId: input.projectId,
workspaceId: ctx.workspace.id,
})

const project = res.unwrap()

return { ...ctx, project }
})
34 changes: 30 additions & 4 deletions apps/web/src/components/Sidebar/DocumentTree/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
'use client'

import { faker } from '@faker-js/faker'
import type { DocumentType, DocumentVersion } from '@latitude-data/core'
import type {
Commit,
DocumentType,
DocumentVersion,
Node,
} from '@latitude-data/core'
import { useCurrentCommit, useCurrentProject } from '@latitude-data/web-ui'
import useCommits from '$/stores/commits'
import useDocumentVersions from '$/stores/documentVersions'

import { Node, useTree } from '../toTree'
import { useTree } from './useTree'

function generateName() {
return faker.science.chemicalElement().name
Expand Down Expand Up @@ -91,17 +97,37 @@ function TreeNode({ node, level = 0 }: { node: Node; level?: number }) {
}

export default function DocumentTree({
commits: serverCommits,
documents: serverDocuments,
}: {
commits: Commit[]
documents: DocumentVersion[]
}) {
const { commit } = useCurrentCommit()
const { project } = useCurrentProject()
const { documents } = useDocumentVersions(
const { data: documents } = useDocumentVersions(
{ commitUuid: commit.uuid, projectId: project.id },
{ fallbackData: serverDocuments },
)
const { create } = useCommits(
{ projectId: project.id },
{
fallbackData: serverCommits,
},
)

const rootNode = useTree({ documents })

return <TreeNode node={rootNode} />
return (
<div className='flex flex-col gap-12 pt-4 pl-4'>
<button onClick={() => create()}>Create commit</button>
<div className='flex flex-col gap-4'>
<div className='flex flex-row align-items justify-between'>
<h2 className='font-bold'>Create document</h2>
<CreateNode />
</div>
<TreeNode node={rootNode} />
</div>
</div>
)
}
7 changes: 7 additions & 0 deletions apps/web/src/components/Sidebar/DocumentTree/useTree.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { useMemo } from 'react'

import { DocumentVersion, toTree } from '@latitude-data/core'

export function useTree({ documents }: { documents: DocumentVersion[] }) {
return useMemo(() => toTree(documents), [documents])
}
31 changes: 8 additions & 23 deletions apps/web/src/components/Sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,14 @@
import { materializeDocumentsAtCommit } from '@latitude-data/core'
import { listCommits, materializeDocumentsAtCommit } from '@latitude-data/core'

import DocumentTree, { CreateNode } from './DocumentTree'
import DocumentTree from './DocumentTree'

export default async function Sidebar({
commitUuid,
projectId,
}: {
commitUuid: string
projectId: number
}) {
const documentsResult = await materializeDocumentsAtCommit({
projectId,
export default async function Sidebar({ commitUuid }: { commitUuid: string }) {
const docsResult = await materializeDocumentsAtCommit({
commitUuid,
})
const documents = documentsResult.unwrap()

return (
<div className='flex flex-col gap-4 p-4'>
<div className='flex flex-row align-items justify-between'>
<h2>Prompts</h2>
<div className='flex flex-row gap-2 align-items'>
<CreateNode />
</div>
</div>
<DocumentTree documents={documents} />
</div>
)
// TODO: wrap data-access reads in transaction blocks and make use of result
const commits = await listCommits()

return <DocumentTree commits={commits} documents={docsResult.unwrap()} />
}
Loading

0 comments on commit df22a4f

Please sign in to comment.