feat: move db schemas back to api

pull/715/head
Travis Fischer 2025-05-22 02:14:46 +07:00
rodzic 07dc9e60d1
commit cfff2d37fc
36 zmienionych plików z 199 dodań i 275 usunięć

Wyświetl plik

@ -5,7 +5,7 @@ import { defineConfig } from 'drizzle-kit'
export default defineConfig({
out: './drizzle',
schema: './src/db/schema.ts',
schema: './src/db/schema/index.ts',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL!

Wyświetl plik

@ -12,7 +12,6 @@ export default [
...drizzle.configs.recommended.rules,
'no-console': 'error',
'unicorn/no-array-reduce': 'off'
// 'no-restricted-imports': ['error', '@agentic/platform-db']
}
},
{

Wyświetl plik

@ -27,11 +27,13 @@
},
"dependencies": {
"@agentic/platform-core": "workspace:*",
"@agentic/platform-db": "workspace:*",
"@agentic/platform-validators": "workspace:*",
"@fisch0920/drizzle-orm": "^0.43.7",
"@fisch0920/drizzle-zod": "^0.7.9",
"@hono/node-server": "^1.14.1",
"@hono/sentry": "^1.2.1",
"@hono/zod-openapi": "^0.19.6",
"@paralleldrive/cuid2": "^2.2.2",
"@redocly/openapi-core": "^1.34.3",
"@sentry/node": "^9.19.0",
"better-auth": "^1.2.8",
@ -41,6 +43,7 @@
"jsonwebtoken": "^9.0.2",
"p-all": "^5.0.0",
"parse-json": "^8.3.0",
"postgres": "^3.4.5",
"restore-cursor": "catalog:",
"semver": "^7.7.2",
"stripe": "^18.1.0",

Wyświetl plik

@ -31,8 +31,8 @@ import { registerV1TeamsMembersCreateTeamMember } from './teams/members/create-t
import { registerV1TeamsMembersDeleteTeamMember } from './teams/members/delete-team-member'
import { registerV1TeamsMembersUpdateTeamMember } from './teams/members/update-team-member'
import { registerV1TeamsUpdateTeam } from './teams/update-team'
import { registerV1UsersGetUser } from './users/get-user'
import { registerV1UsersUpdateUser } from './users/update-user'
// import { registerV1UsersGetUser } from './users/get-user'
// import { registerV1UsersUpdateUser } from './users/update-user'
import { registerV1StripeWebhook } from './webhooks/stripe-webhook'
export const apiV1 = new OpenAPIHono({
@ -65,8 +65,8 @@ const privateRouter = new OpenAPIHono<AuthenticatedEnv>()
registerHealthCheck(publicRouter)
// Users
registerV1UsersGetUser(privateRouter)
registerV1UsersUpdateUser(privateRouter)
// registerV1UsersGetUser(privateRouter)
// registerV1UsersUpdateUser(privateRouter)
// Teams
registerV1TeamsCreateTeam(privateRouter)

Wyświetl plik

@ -1,51 +1,51 @@
import { assert, parseZodSchema } from '@agentic/platform-core'
import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
// import { assert, parseZodSchema } from '@agentic/platform-core'
// import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db'
import { acl } from '@/lib/acl'
import {
openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404,
openapiErrorResponses
} from '@/lib/openapi-utils'
// import type { AuthenticatedEnv } from '@/lib/types'
// import { db, eq, schema } from '@/db'
// import { acl } from '@/lib/acl'
// import {
// openapiAuthenticatedSecuritySchemas,
// openapiErrorResponse404,
// openapiErrorResponses
// } from '@/lib/openapi-utils'
import { userIdParamsSchema } from './schemas'
// import { userIdParamsSchema } from './schemas'
const route = createRoute({
description: 'Gets a user',
tags: ['users'],
operationId: 'getUser',
method: 'get',
path: 'users/{userId}',
security: openapiAuthenticatedSecuritySchemas,
request: {
params: userIdParamsSchema
},
responses: {
200: {
description: 'A user object',
content: {
'application/json': {
schema: schema.userSelectSchema
}
}
},
...openapiErrorResponses,
...openapiErrorResponse404
}
})
// const route = createRoute({
// description: 'Gets a user',
// tags: ['users'],
// operationId: 'getUser',
// method: 'get',
// path: 'users/{userId}',
// security: openapiAuthenticatedSecuritySchemas,
// request: {
// params: userIdParamsSchema
// },
// responses: {
// 200: {
// description: 'A user object',
// content: {
// 'application/json': {
// schema: schema.userSelectSchema
// }
// }
// },
// ...openapiErrorResponses,
// ...openapiErrorResponse404
// }
// })
export function registerV1UsersGetUser(app: OpenAPIHono<AuthenticatedEnv>) {
return app.openapi(route, async (c) => {
const { userId } = c.req.valid('param')
await acl(c, { userId }, { label: 'User' })
// export function registerV1UsersGetUser(app: OpenAPIHono<AuthenticatedEnv>) {
// return app.openapi(route, async (c) => {
// const { userId } = c.req.valid('param')
// await acl(c, { userId }, { label: 'User' })
const user = await db.query.users.findFirst({
where: eq(schema.users.id, userId)
})
assert(user, 404, `User not found "${userId}"`)
// const user = await db.query.users.findFirst({
// where: eq(schema.users.id, userId)
// })
// assert(user, 404, `User not found "${userId}"`)
return c.json(parseZodSchema(schema.userSelectSchema, user))
})
}
// return c.json(parseZodSchema(schema.userSelectSchema, user))
// })
// }

Wyświetl plik

@ -1,62 +1,62 @@
import { assert, parseZodSchema } from '@agentic/platform-core'
import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
// import { assert, parseZodSchema } from '@agentic/platform-core'
// import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
import type { AuthenticatedEnv } from '@/lib/types'
import { db, eq, schema } from '@/db'
import { acl } from '@/lib/acl'
import {
openapiAuthenticatedSecuritySchemas,
openapiErrorResponse404,
openapiErrorResponses
} from '@/lib/openapi-utils'
// import type { AuthenticatedEnv } from '@/lib/types'
// import { db, eq, schema } from '@/db'
// import { acl } from '@/lib/acl'
// import {
// openapiAuthenticatedSecuritySchemas,
// openapiErrorResponse404,
// openapiErrorResponses
// } from '@/lib/openapi-utils'
import { userIdParamsSchema } from './schemas'
// import { userIdParamsSchema } from './schemas'
const route = createRoute({
description: 'Updates a user',
tags: ['users'],
operationId: 'updateUser',
method: 'post',
path: 'users/{userId}',
security: openapiAuthenticatedSecuritySchemas,
request: {
params: userIdParamsSchema,
body: {
required: true,
content: {
'application/json': {
schema: schema.userUpdateSchema
}
}
}
},
responses: {
200: {
description: 'A user object',
content: {
'application/json': {
schema: schema.userSelectSchema
}
}
},
...openapiErrorResponses,
...openapiErrorResponse404
}
})
// const route = createRoute({
// description: 'Updates a user',
// tags: ['users'],
// operationId: 'updateUser',
// method: 'post',
// path: 'users/{userId}',
// security: openapiAuthenticatedSecuritySchemas,
// request: {
// params: userIdParamsSchema,
// body: {
// required: true,
// content: {
// 'application/json': {
// schema: schema.userUpdateSchema
// }
// }
// }
// },
// responses: {
// 200: {
// description: 'A user object',
// content: {
// 'application/json': {
// schema: schema.userSelectSchema
// }
// }
// },
// ...openapiErrorResponses,
// ...openapiErrorResponse404
// }
// })
export function registerV1UsersUpdateUser(app: OpenAPIHono<AuthenticatedEnv>) {
return app.openapi(route, async (c) => {
const { userId } = c.req.valid('param')
await acl(c, { userId }, { label: 'User' })
const body = c.req.valid('json')
// export function registerV1UsersUpdateUser(app: OpenAPIHono<AuthenticatedEnv>) {
// return app.openapi(route, async (c) => {
// const { userId } = c.req.valid('param')
// await acl(c, { userId }, { label: 'User' })
// const body = c.req.valid('json')
const [user] = await db
.update(schema.users)
.set(body)
.where(eq(schema.users.id, userId))
.returning()
assert(user, 404, `User not found "${userId}"`)
// const [user] = await db
// .update(schema.users)
// .set(body)
// .where(eq(schema.users.id, userId))
// .returning()
// assert(user, 404, `User not found "${userId}"`)
return c.json(parseZodSchema(schema.userSelectSchema, user))
})
}
// return c.json(parseZodSchema(schema.userSelectSchema, user))
// })
// }

Wyświetl plik

@ -1,18 +1,54 @@
// The only place we allow `@agentic/platform-db` imports is in this directory.
import {
drizzle,
postgres,
type PostgresClient,
schema
} from '@agentic/platform-db'
import { drizzle } from '@fisch0920/drizzle-orm/postgres-js'
import postgres from 'postgres'
import { env } from '@/lib/env'
import * as schema from './schema'
type PostgresClient = ReturnType<typeof postgres>
let _postgresClient: PostgresClient | undefined
const postgresClient =
_postgresClient ?? (_postgresClient = postgres(env.DATABASE_URL))
export const db = drizzle({ client: postgresClient, schema })
export * from '@agentic/platform-db'
export * as schema from './schema'
export {
createIdForModel,
idMaxLength,
idPrefixMap,
type ModelType
} from './schema/common'
export * from './schema/schemas'
export * from './schemas'
export type * from './types'
export * from './utils'
export {
and,
arrayContained,
arrayContains,
arrayOverlaps,
asc,
between,
desc,
eq,
exists,
gt,
gte,
ilike,
inArray,
isNotNull,
isNull,
like,
lt,
lte,
ne,
not,
notBetween,
notExists,
notIlike,
notInArray,
notLike,
or
} from '@fisch0920/drizzle-orm'

Wyświetl plik

@ -1,3 +0,0 @@
// The only place we allow `@agentic/platform-db` imports is in this directory.
export * from '@agentic/platform-db'

Wyświetl plik

@ -11,6 +11,7 @@ import {
createSelectSchema,
stripeId,
timestamps,
username,
// username,
userPrimaryId,
userRoleEnum
@ -31,7 +32,7 @@ export const users = pgTable(
image: text('image'),
// TODO: re-add username
// username: username().notNull().unique(),
username: username(),
role: userRoleEnum().default('user').notNull(),
isStripeConnectEnabledByDefault: boolean().default(true).notNull(),

Wyświetl plik

@ -1,6 +1,7 @@
// import { validators } from '@agentic/platform-validators'
import { validators } from '@agentic/platform-validators'
import { betterAuth } from 'better-auth'
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
import { username } from 'better-auth/plugins'
import { createIdForModel, db } from '@/db'
@ -51,11 +52,10 @@ export const auth = betterAuth({
database: {
generateId: ({ model }) => createIdForModel(model as any)
}
}
// TODO
// plugins: [
// username({
// usernameValidator: validators.username
// })
// ]
},
plugins: [
username({
usernameValidator: validators.username
})
]
})

Wyświetl plik

@ -38,7 +38,8 @@ export async function upsertStripeCustomer(ctx: AuthenticatedContext): Promise<{
// TODO: add more metadata referencing signup LogEntry
const metadata = {
userId: user.id,
username: user.username
email: user.email,
username: user.username ?? null
}
const stripeCustomer = await stripe.customers.create({

Wyświetl plik

@ -16,7 +16,7 @@ export const authenticate = createMiddleware<AuthenticatedEnv>(
assert(session.session, 401, 'Unauthorized')
ctx.set('userId', session.user.id)
ctx.set('user', session.user)
ctx.set('user', session.user as any) // TODO: resolve AuthUser and RawUser types
ctx.set('session', session.session)
await next()

Wyświetl plik

@ -1,6 +1,6 @@
import type { Context } from 'hono'
import type { RawTeamMember } from '@/db'
import type { RawTeamMember, RawUser } from '@/db'
import type { auth } from './auth'
import type { Env } from './env'
@ -11,7 +11,7 @@ export type { OpenAPI3 as LooseOpenAPI3Spec } from 'openapi-typescript'
export type Environment = Env['NODE_ENV']
export type Service = 'api'
export type AuthUser = typeof auth.$Infer.Session.user
// export type AuthUser = typeof auth.$Infer.Session.user
export type AuthSession = typeof auth.$Infer.Session.session
export type DefaultEnvVariables = {
@ -21,7 +21,7 @@ export type DefaultEnvVariables = {
export type AuthenticatedEnvVariables = DefaultEnvVariables & {
userId: string
user?: AuthUser
user?: RawUser
session?: AuthSession
teamMember?: RawTeamMember
}

Wyświetl plik

@ -27,8 +27,9 @@
"test:typecheck": "tsc --noEmit"
},
"dependencies": {
"@agentic/platform-core": "workspace:*",
"@agentic/platform-api-client": "workspace:*",
"@agentic/platform-core": "workspace:*",
"better-auth": "^1.2.8",
"commander": "^14.0.0",
"conf": "^13.1.0",
"inquirer": "^9.2.15",

Wyświetl plik

@ -1,3 +1,4 @@
import { createAuthClient } from 'better-auth/client'
import { Command } from 'commander'
import restoreCursor from 'restore-cursor'
@ -8,9 +9,19 @@ import { publish } from './commands/publish'
import { rm } from './commands/rm'
import { signin } from './commands/signin'
const authClient = createAuthClient({
baseURL: 'http://localhost:3000/v1/auth'
})
async function main() {
restoreCursor()
const res = await authClient.signIn.social({
provider: 'github'
})
console.log(res)
return
const program = new Command()
program.addCommand(signin)
program.addCommand(get)

Wyświetl plik

@ -1,41 +0,0 @@
{
"name": "@agentic/platform-db",
"private": true,
"version": "0.0.1",
"description": "Postgres database schemas and types for the Agentic platform using Drizzle as the ORM.",
"author": "Travis Fischer <travis@transitivebullsh.it>",
"license": "UNLICENSED",
"repository": {
"type": "git",
"url": "git+https://github.com/transitive-bullshit/agentic-platform.git",
"directory": "packages/db"
},
"type": "module",
"main": "./src/index.ts",
"source": "./src/index.ts",
"types": "./src/index.ts",
"sideEffects": false,
"exports": {
".": "./src/index.ts"
},
"scripts": {
"test": "run-s test:*",
"test:lint": "eslint .",
"test:typecheck": "tsc --noEmit",
"test:unit": "vitest run"
},
"dependencies": {
"@agentic/platform-core": "workspace:*",
"@agentic/platform-validators": "workspace:*",
"@fisch0920/drizzle-orm": "^0.43.7",
"@fisch0920/drizzle-zod": "^0.7.9",
"@hono/zod-openapi": "^0.19.6",
"@paralleldrive/cuid2": "^2.2.2",
"bcryptjs": "^3.0.2",
"hono": "^4.7.9",
"parse-json": "^8.3.0",
"postgres": "^3.4.5",
"type-fest": "catalog:",
"zod": "catalog:"
}
}

Wyświetl plik

@ -1,46 +0,0 @@
import type postgres from 'postgres'
export { drizzle } from '@fisch0920/drizzle-orm/postgres-js'
export type PostgresClient = ReturnType<typeof postgres>
export * as schema from './schema'
export {
createIdForModel,
idMaxLength,
idPrefixMap,
type ModelType
} from './schema/common'
export * from './schema/schemas'
export * from './schemas'
export type * from './types'
export * from './utils'
export {
and,
arrayContained,
arrayContains,
arrayOverlaps,
asc,
between,
desc,
eq,
exists,
gt,
gte,
ilike,
inArray,
isNotNull,
isNull,
like,
lt,
lte,
ne,
not,
notBetween,
notExists,
notIlike,
notInArray,
notLike,
or
} from '@fisch0920/drizzle-orm'
export { default as postgres } from 'postgres'

Wyświetl plik

@ -1,5 +0,0 @@
{
"extends": "@fisch0920/config/tsconfig-node",
"include": ["src", "*.config.ts"],
"exclude": ["node_modules"]
}

Wyświetl plik

@ -131,12 +131,15 @@ importers:
'@agentic/platform-core':
specifier: workspace:*
version: link:../../packages/core
'@agentic/platform-db':
specifier: workspace:*
version: link:../../packages/db
'@agentic/platform-validators':
specifier: workspace:*
version: link:../../packages/validators
'@fisch0920/drizzle-orm':
specifier: ^0.43.7
version: 0.43.7(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(kysely@0.28.2)(postgres@3.4.5)
'@fisch0920/drizzle-zod':
specifier: ^0.7.9
version: 0.7.9(@fisch0920/drizzle-orm@0.43.7(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(kysely@0.28.2)(postgres@3.4.5))(zod@3.24.4)
'@hono/node-server':
specifier: ^1.14.1
version: 1.14.1(hono@4.7.9)
@ -146,6 +149,9 @@ importers:
'@hono/zod-openapi':
specifier: ^0.19.6
version: 0.19.6(hono@4.7.9)(zod@3.24.4)
'@paralleldrive/cuid2':
specifier: ^2.2.2
version: 2.2.2
'@redocly/openapi-core':
specifier: ^1.34.3
version: 1.34.3(supports-color@10.0.0)
@ -173,6 +179,9 @@ importers:
parse-json:
specifier: ^8.3.0
version: 8.3.0
postgres:
specifier: ^3.4.5
version: 3.4.5
restore-cursor:
specifier: 'catalog:'
version: 5.1.0
@ -229,6 +238,9 @@ importers:
'@agentic/platform-core':
specifier: workspace:*
version: link:../core
better-auth:
specifier: ^1.2.8
version: 1.2.8
commander:
specifier: ^14.0.0
version: 14.0.0
@ -271,45 +283,6 @@ importers:
specifier: ^4.7.9
version: 4.7.9
packages/db:
dependencies:
'@agentic/platform-core':
specifier: workspace:*
version: link:../core
'@agentic/platform-validators':
specifier: workspace:*
version: link:../validators
'@fisch0920/drizzle-orm':
specifier: ^0.43.7
version: 0.43.7(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(kysely@0.28.2)(postgres@3.4.5)
'@fisch0920/drizzle-zod':
specifier: ^0.7.9
version: 0.7.9(@fisch0920/drizzle-orm@0.43.7(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(kysely@0.28.2)(postgres@3.4.5))(zod@3.24.4)
'@hono/zod-openapi':
specifier: ^0.19.6
version: 0.19.6(hono@4.7.9)(zod@3.24.4)
'@paralleldrive/cuid2':
specifier: ^2.2.2
version: 2.2.2
bcryptjs:
specifier: ^3.0.2
version: 3.0.2
hono:
specifier: ^4.7.9
version: 4.7.9
parse-json:
specifier: ^8.3.0
version: 8.3.0
postgres:
specifier: ^3.4.5
version: 3.4.5
type-fest:
specifier: 'catalog:'
version: 4.41.0
zod:
specifier: 'catalog:'
version: 3.24.4
packages/validators:
dependencies:
'@paralleldrive/cuid2':
@ -1544,10 +1517,6 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
bcryptjs@3.0.2:
resolution: {integrity: sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==}
hasBin: true
better-auth@1.2.8:
resolution: {integrity: sha512-y8ry7ZW3/3ZIr82Eo1zUDtMzdoQlFnwNuZ0+b0RxoNZgqmvgTIc/0tCDC7NDJerqSu4UCzer0dvYxBsv3WMIGg==}
@ -5135,8 +5104,6 @@ snapshots:
base64-js@1.5.1: {}
bcryptjs@3.0.2: {}
better-auth@1.2.8:
dependencies:
'@better-auth/utils': 0.2.5