kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: move db schemas to separate package to share types
rodzic
d0539ecaff
commit
4ec31b176c
|
@ -5,7 +5,7 @@ import { defineConfig } from 'drizzle-kit'
|
|||
|
||||
export default defineConfig({
|
||||
out: './drizzle',
|
||||
schema: './src/db/schema/index.ts',
|
||||
schema: './src/db/schema.ts',
|
||||
dialect: 'postgresql',
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL!
|
||||
|
|
|
@ -10,7 +10,10 @@ export default [
|
|||
drizzle
|
||||
},
|
||||
rules: {
|
||||
...drizzle.configs.recommended.rules
|
||||
...drizzle.configs.recommended.rules,
|
||||
'no-console': 'error',
|
||||
'unicorn/no-array-reduce': 'off',
|
||||
'no-restricted-imports': ['error', '@agentic/platform-db']
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -23,29 +23,23 @@
|
|||
"clean": "del dist",
|
||||
"test": "run-s test:*",
|
||||
"test:lint": "eslint .",
|
||||
"test:typecheck": "tsc --noEmit",
|
||||
"test:unit": "vitest run"
|
||||
"test:typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agentic/platform-core": "workspace:*",
|
||||
"@agentic/validators": "workspace:*",
|
||||
"@fisch0920/drizzle-orm": "^0.43.7",
|
||||
"@fisch0920/drizzle-zod": "^0.7.9",
|
||||
"@agentic/platform-db": "workspace:*",
|
||||
"@agentic/platform-validators": "workspace:*",
|
||||
"@hono/node-server": "^1.14.1",
|
||||
"@hono/sentry": "^1.2.1",
|
||||
"@hono/zod-openapi": "^0.19.6",
|
||||
"@hono/zod-validator": "^0.5.0",
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@redocly/openapi-core": "^1.34.3",
|
||||
"@sentry/node": "^9.19.0",
|
||||
"bcryptjs": "^3.0.2",
|
||||
"eventid": "^2.0.1",
|
||||
"exit-hook": "catalog:",
|
||||
"hono": "^4.7.9",
|
||||
"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",
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
import { consumerIdSchema, paginationSchema } from '@/db'
|
||||
import { consumerRelationsSchema } from '@/db/schema'
|
||||
import {
|
||||
consumerIdSchema,
|
||||
consumerRelationsSchema,
|
||||
paginationSchema
|
||||
} from '@/db'
|
||||
|
||||
export const consumerIdParamsSchema = z.object({
|
||||
consumerId: consumerIdSchema.openapi({
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { assert, parseZodSchema, pick, sha256 } from '@agentic/platform-core'
|
||||
import { validators } from '@agentic/validators'
|
||||
import { validators } from '@agentic/platform-validators'
|
||||
import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
|
||||
|
||||
import type { AuthenticatedEnv } from '@/lib/types'
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
import { deploymentIdSchema, paginationSchema, projectIdSchema } from '@/db'
|
||||
import { deploymentRelationsSchema } from '@/db/schema'
|
||||
import {
|
||||
deploymentIdSchema,
|
||||
deploymentRelationsSchema,
|
||||
paginationSchema,
|
||||
projectIdSchema
|
||||
} from '@/db'
|
||||
|
||||
export const deploymentIdParamsSchema = z.object({
|
||||
deploymentId: deploymentIdSchema.openapi({
|
||||
|
|
|
@ -110,35 +110,36 @@ apiV1.route('/', privateRouter)
|
|||
|
||||
// API route types to be used by Hono's RPC client.
|
||||
// Should include all routes except for internal and admin routes.
|
||||
export type ApiRoutes =
|
||||
| ReturnType<typeof registerHealthCheck>
|
||||
// Users
|
||||
| ReturnType<typeof registerV1UsersGetUser>
|
||||
| ReturnType<typeof registerV1UsersUpdateUser>
|
||||
// Teams
|
||||
| ReturnType<typeof registerV1TeamsCreateTeam>
|
||||
| ReturnType<typeof registerV1TeamsListTeams>
|
||||
| ReturnType<typeof registerV1TeamsGetTeam>
|
||||
| ReturnType<typeof registerV1TeamsDeleteTeam>
|
||||
| ReturnType<typeof registerV1TeamsUpdateTeam>
|
||||
// Team members
|
||||
| ReturnType<typeof registerV1TeamsMembersCreateTeamMember>
|
||||
| ReturnType<typeof registerV1TeamsMembersUpdateTeamMember>
|
||||
| ReturnType<typeof registerV1TeamsMembersDeleteTeamMember>
|
||||
// Projects
|
||||
| ReturnType<typeof registerV1ProjectsCreateProject>
|
||||
| ReturnType<typeof registerV1ProjectsListProjects>
|
||||
| ReturnType<typeof registerV1ProjectsGetProject>
|
||||
| ReturnType<typeof registerV1ProjectsUpdateProject>
|
||||
// Consumers
|
||||
| ReturnType<typeof registerV1ConsumersGetConsumer>
|
||||
| ReturnType<typeof registerV1ConsumersCreateConsumer>
|
||||
| ReturnType<typeof registerV1ConsumersUpdateConsumer>
|
||||
| ReturnType<typeof registerV1ConsumersRefreshConsumerToken>
|
||||
| ReturnType<typeof registerV1ProjectsListConsumers>
|
||||
// Deployments
|
||||
| ReturnType<typeof registerV1DeploymentsGetDeployment>
|
||||
| ReturnType<typeof registerV1DeploymentsCreateDeployment>
|
||||
| ReturnType<typeof registerV1DeploymentsUpdateDeployment>
|
||||
| ReturnType<typeof registerV1DeploymentsListDeployments>
|
||||
| ReturnType<typeof registerV1DeploymentsPublishDeployment>
|
||||
// NOTE: Removing for now because Hono's RPC client / types are clunky and slow.
|
||||
// export type ApiRoutes =
|
||||
// | ReturnType<typeof registerHealthCheck>
|
||||
// // Users
|
||||
// | ReturnType<typeof registerV1UsersGetUser>
|
||||
// | ReturnType<typeof registerV1UsersUpdateUser>
|
||||
// // Teams
|
||||
// | ReturnType<typeof registerV1TeamsCreateTeam>
|
||||
// | ReturnType<typeof registerV1TeamsListTeams>
|
||||
// | ReturnType<typeof registerV1TeamsGetTeam>
|
||||
// | ReturnType<typeof registerV1TeamsDeleteTeam>
|
||||
// | ReturnType<typeof registerV1TeamsUpdateTeam>
|
||||
// // Team members
|
||||
// | ReturnType<typeof registerV1TeamsMembersCreateTeamMember>
|
||||
// | ReturnType<typeof registerV1TeamsMembersUpdateTeamMember>
|
||||
// | ReturnType<typeof registerV1TeamsMembersDeleteTeamMember>
|
||||
// // Projects
|
||||
// | ReturnType<typeof registerV1ProjectsCreateProject>
|
||||
// | ReturnType<typeof registerV1ProjectsListProjects>
|
||||
// | ReturnType<typeof registerV1ProjectsGetProject>
|
||||
// | ReturnType<typeof registerV1ProjectsUpdateProject>
|
||||
// // Consumers
|
||||
// | ReturnType<typeof registerV1ConsumersGetConsumer>
|
||||
// | ReturnType<typeof registerV1ConsumersCreateConsumer>
|
||||
// | ReturnType<typeof registerV1ConsumersUpdateConsumer>
|
||||
// | ReturnType<typeof registerV1ConsumersRefreshConsumerToken>
|
||||
// | ReturnType<typeof registerV1ProjectsListConsumers>
|
||||
// // Deployments
|
||||
// | ReturnType<typeof registerV1DeploymentsGetDeployment>
|
||||
// | ReturnType<typeof registerV1DeploymentsCreateDeployment>
|
||||
// | ReturnType<typeof registerV1DeploymentsUpdateDeployment>
|
||||
// | ReturnType<typeof registerV1DeploymentsListDeployments>
|
||||
// | ReturnType<typeof registerV1DeploymentsPublishDeployment>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
import { paginationSchema, projectIdSchema } from '@/db'
|
||||
import { projectRelationsSchema } from '@/db/schema'
|
||||
import { paginationSchema, projectIdSchema, projectRelationsSchema } from '@/db'
|
||||
|
||||
export const projectIdParamsSchema = z.object({
|
||||
projectId: projectIdSchema.openapi({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { OpenAPIHono } from '@hono/zod-openapi'
|
||||
import type Stripe from 'stripe'
|
||||
import { assert,HttpError } from '@agentic/platform-core'
|
||||
import { assert, HttpError } from '@agentic/platform-core'
|
||||
|
||||
import { and, db, eq, schema } from '@/db'
|
||||
import { env, isStripeLive } from '@/lib/env'
|
||||
|
|
|
@ -1,44 +1,20 @@
|
|||
import { drizzle } from '@fisch0920/drizzle-orm/postgres-js'
|
||||
import postgres from 'postgres'
|
||||
// The only place we allow `@agentic/platform-db` imports is in this directory.
|
||||
|
||||
|
||||
import {
|
||||
drizzle,
|
||||
postgres,
|
||||
type PostgresClient,
|
||||
schema
|
||||
} from '@agentic/platform-db'
|
||||
|
||||
import { env } from '@/lib/env'
|
||||
|
||||
import * as schema from './schema'
|
||||
|
||||
let _postgresClient: ReturnType<typeof postgres> | undefined
|
||||
let _postgresClient: PostgresClient | undefined
|
||||
const postgresClient =
|
||||
_postgresClient ?? (_postgresClient = postgres(env.DATABASE_URL))
|
||||
|
||||
export const db = drizzle({ client: postgresClient, schema })
|
||||
|
||||
export * as schema from './schema'
|
||||
export * from './schemas'
|
||||
export type * from './types'
|
||||
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 * from '@agentic/platform-db'
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
// The only place we allow `@agentic/platform-db` imports is in this directory.
|
||||
|
||||
|
||||
export * from '@agentic/platform-db'
|
|
@ -1,5 +1,5 @@
|
|||
import { assert } from '@agentic/platform-core'
|
||||
import { parseFaasIdentifier } from '@agentic/validators'
|
||||
import { parseFaasIdentifier } from '@agentic/platform-validators'
|
||||
|
||||
import type { AuthenticatedContext } from '@/lib/types'
|
||||
import { and, db, eq, schema } from '@/db'
|
||||
|
|
|
@ -2,14 +2,18 @@ import type Stripe from 'stripe'
|
|||
import { assert } from '@agentic/platform-core'
|
||||
import pAll from 'p-all'
|
||||
|
||||
import { db, eq, type RawDeployment, type RawProject, schema } from '@/db'
|
||||
import {
|
||||
db,
|
||||
eq,
|
||||
getLabelForPricingInterval,
|
||||
getPricingPlanLineItemHashForStripePrice,
|
||||
getPricingPlansByInterval,
|
||||
type PricingPlan,
|
||||
type PricingPlanLineItem
|
||||
} from '@/db/schema'
|
||||
type PricingPlanLineItem,
|
||||
type RawDeployment,
|
||||
type RawProject,
|
||||
schema
|
||||
} from '@/db'
|
||||
import { stripe } from '@/lib/stripe'
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,13 +6,13 @@ import {
|
|||
type ConsumerUpdate,
|
||||
db,
|
||||
eq,
|
||||
getStripePriceIdForPricingPlanLineItem,
|
||||
type RawConsumer,
|
||||
type RawDeployment,
|
||||
type RawProject,
|
||||
type RawUser,
|
||||
schema
|
||||
} from '@/db'
|
||||
import { getStripePriceIdForPricingPlanLineItem } from '@/db/schema'
|
||||
import { stripe } from '@/lib/stripe'
|
||||
|
||||
export async function upsertStripeSubscription(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { assert } from '@agentic/platform-core'
|
||||
import semver from 'semver'
|
||||
|
||||
import type { RawProject } from '@/db/types'
|
||||
import type { RawProject } from '@/db'
|
||||
|
||||
export function normalizeDeploymentVersion({
|
||||
deploymentId,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { assert } from '@agentic/platform-core'
|
||||
import { parseFaasIdentifier } from '@agentic/validators'
|
||||
import { parseFaasIdentifier } from '@agentic/platform-validators'
|
||||
|
||||
import type { AuthenticatedContext } from '@/lib/types'
|
||||
import { db, eq, type RawDeployment, schema } from '@/db'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { assert } from '@agentic/platform-core'
|
||||
|
||||
import type { DeploymentOriginAdapter } from '@/db/schema'
|
||||
import type { DeploymentOriginAdapter } from '@/db'
|
||||
import type { Logger } from '@/lib/logger'
|
||||
import { validateOpenAPISpec } from '@/lib/validate-openapi-spec'
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { assert } from '@agentic/platform-core'
|
||||
import { and, eq } from '@fisch0920/drizzle-orm'
|
||||
import { createMiddleware } from 'hono/factory'
|
||||
|
||||
import type { AuthenticatedEnv } from '@/lib/types'
|
||||
import { db, schema } from '@/db'
|
||||
import { and, db, eq, schema } from '@/db'
|
||||
import { aclTeamMember } from '@/lib/acl-team-member'
|
||||
|
||||
export const team = createMiddleware<AuthenticatedEnv>(
|
||||
|
|
|
@ -38,5 +38,3 @@ initExitHooks({ server })
|
|||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Server running on port ${env.PORT}`)
|
||||
|
||||
export { type ApiRoutes } from '@/api-v1'
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
"scripts": {
|
||||
"test": "run-s test:*",
|
||||
"test:lint": "eslint .",
|
||||
"test:typecheck": "tsc --noEmit",
|
||||
"test:unit": "vitest run"
|
||||
"test:typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agentic/platform-core": "workspace:*",
|
||||
|
@ -35,6 +34,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@agentic/platform-api": "workspace:*",
|
||||
"@agentic/platform-db": "workspace:*",
|
||||
"@commander-js/extra-typings": "^14.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
|
|
@ -8,6 +8,8 @@ export const signin = new Command('login')
|
|||
.option('-u, --username <username>', 'account username')
|
||||
.option('-e, --email <email>', 'account email')
|
||||
.option('-p, --password <password>', 'account password')
|
||||
.action(async (opts) => {
|
||||
.action(async (_opts) => {
|
||||
// TODO
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('TODO: signin')
|
||||
})
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import { Command } from 'commander'
|
||||
import { getAuth, requireAuth } from '../store'
|
||||
|
||||
import { getAuth } from '../store'
|
||||
|
||||
export const whoami = new Command('whoami')
|
||||
.description('Displays info about the current user')
|
||||
.action(async (opts) => {
|
||||
.action(async () => {
|
||||
const auth = getAuth()
|
||||
|
||||
// TODO
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
JSON.stringify({ user: auth.user, team: auth.teamSlug }, null, 2)
|
||||
)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import type { User } from '@agentic/platform-db'
|
||||
import { assert } from '@agentic/platform-core'
|
||||
import Conf from 'conf'
|
||||
|
||||
|
@ -5,7 +6,7 @@ export const store = new Conf({ projectName: 'agentic' })
|
|||
|
||||
export type Auth = {
|
||||
token: string
|
||||
user: string
|
||||
user: User
|
||||
teamId?: string
|
||||
teamSlug?: string
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"name": "@agentic/platform-db",
|
||||
"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:"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
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 * 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'
|
|
@ -1,4 +1,3 @@
|
|||
import { hashObject } from '@agentic/platform-core'
|
||||
import { type Equal, sql, type Writable } from '@fisch0920/drizzle-orm'
|
||||
import {
|
||||
pgEnum,
|
||||
|
@ -14,14 +13,6 @@ import { createSchemaFactory } from '@fisch0920/drizzle-zod'
|
|||
import { z } from '@hono/zod-openapi'
|
||||
import { createId } from '@paralleldrive/cuid2'
|
||||
|
||||
import type { RawProject } from '../types'
|
||||
import type {
|
||||
PricingInterval,
|
||||
PricingPlan,
|
||||
PricingPlanLineItem,
|
||||
PricingPlanList
|
||||
} from './schemas'
|
||||
|
||||
const usernameAndTeamSlugLength = 64 as const
|
||||
|
||||
/**
|
||||
|
@ -125,85 +116,3 @@ export const { createInsertSchema, createSelectSchema, createUpdateSchema } =
|
|||
date: true
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Gets the hash used to uniquely map a PricingPlanLineItem to its
|
||||
* corresponding Stripe Price in a stable way across deployments within a
|
||||
* project.
|
||||
*
|
||||
* This hash is used as the key for the `Project._stripePriceIdMap`.
|
||||
*/
|
||||
export function getPricingPlanLineItemHashForStripePrice({
|
||||
pricingPlan,
|
||||
pricingPlanLineItem,
|
||||
project
|
||||
}: {
|
||||
pricingPlan: PricingPlan
|
||||
pricingPlanLineItem: PricingPlanLineItem
|
||||
project: RawProject
|
||||
}) {
|
||||
// TODO: use pricingPlan.slug as well here?
|
||||
// TODO: not sure if this is needed or not...
|
||||
// With pricing plan slug:
|
||||
// - 'price:free:base:<hash>'
|
||||
// - 'price:basic-monthly:base:<hash>'
|
||||
// - 'price:basic-monthly:requests:<hash>'
|
||||
// Without pricing plan slug:
|
||||
// - 'price:base:<hash>'
|
||||
// - 'price:base:<hash>'
|
||||
// - 'price:requests:<hash>'
|
||||
|
||||
const hash = hashObject({
|
||||
...pricingPlanLineItem,
|
||||
projectId: project.id,
|
||||
stripeAccountId: project._stripeAccountId,
|
||||
currency: project.pricingCurrency
|
||||
})
|
||||
|
||||
return `price:${pricingPlan.slug}:${pricingPlanLineItem.slug}:${hash}`
|
||||
}
|
||||
|
||||
export function getStripePriceIdForPricingPlanLineItem({
|
||||
pricingPlan,
|
||||
pricingPlanLineItem,
|
||||
project
|
||||
}: {
|
||||
pricingPlan: PricingPlan
|
||||
pricingPlanLineItem: PricingPlanLineItem
|
||||
project: RawProject
|
||||
}): string | undefined {
|
||||
const pricingPlanLineItemHash = getPricingPlanLineItemHashForStripePrice({
|
||||
pricingPlan,
|
||||
pricingPlanLineItem,
|
||||
project
|
||||
})
|
||||
|
||||
return project._stripePriceIdMap[pricingPlanLineItemHash]
|
||||
}
|
||||
|
||||
export function getPricingPlansByInterval({
|
||||
pricingInterval,
|
||||
pricingPlans
|
||||
}: {
|
||||
pricingInterval: PricingInterval
|
||||
pricingPlans: PricingPlanList
|
||||
}): PricingPlan[] {
|
||||
return pricingPlans.filter(
|
||||
(pricingPlan) =>
|
||||
pricingPlan.interval === undefined ||
|
||||
pricingPlan.interval === pricingInterval
|
||||
)
|
||||
}
|
||||
|
||||
const pricingIntervalToLabelMap: Record<PricingInterval, string> = {
|
||||
day: 'daily',
|
||||
week: 'weekly',
|
||||
month: 'monthly',
|
||||
year: 'yearly'
|
||||
}
|
||||
|
||||
export function getLabelForPricingInterval(
|
||||
pricingInterval: PricingInterval
|
||||
): string {
|
||||
return pricingIntervalToLabelMap[pricingInterval]
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { validators } from '@agentic/validators'
|
||||
import { validators } from '@agentic/platform-validators'
|
||||
import { relations } from '@fisch0920/drizzle-orm'
|
||||
import {
|
||||
boolean,
|
||||
|
@ -9,13 +9,6 @@ import {
|
|||
} from '@fisch0920/drizzle-orm/pg-core'
|
||||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
import { deployments, deploymentSelectSchema } from './deployment'
|
||||
import { projects, projectSelectSchema } from './project'
|
||||
import {
|
||||
type StripeSubscriptionItemIdMap,
|
||||
stripeSubscriptionItemIdMapSchema
|
||||
} from './schemas'
|
||||
import { users, userSelectSchema } from './user'
|
||||
import {
|
||||
createInsertSchema,
|
||||
createSelectSchema,
|
||||
|
@ -26,7 +19,14 @@ import {
|
|||
projectId,
|
||||
stripeId,
|
||||
timestamps
|
||||
} from './utils'
|
||||
} from './common'
|
||||
import { deployments, deploymentSelectSchema } from './deployment'
|
||||
import { projects, projectSelectSchema } from './project'
|
||||
import {
|
||||
type StripeSubscriptionItemIdMap,
|
||||
stripeSubscriptionItemIdMapSchema
|
||||
} from './schemas'
|
||||
import { users, userSelectSchema } from './user'
|
||||
|
||||
// TODO: Consumers should be valid for any enabled project like in RapidAPI and GCP.
|
||||
// This may require a separate model to aggregate User Applications.
|
||||
|
@ -128,13 +128,6 @@ export const consumersRelations = relations(consumers, ({ one }) => ({
|
|||
})
|
||||
}))
|
||||
|
||||
export type ConsumerRelationFields = keyof ReturnType<
|
||||
(typeof consumersRelations)['config']
|
||||
>
|
||||
|
||||
export const consumerRelationsSchema: z.ZodType<ConsumerRelationFields> =
|
||||
z.enum(['user', 'project', 'deployment'])
|
||||
|
||||
export const consumerSelectSchema = createSelectSchema(consumers, {
|
||||
_stripeSubscriptionItemIdMap: stripeSubscriptionItemIdMapSchema,
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { validators } from '@agentic/validators'
|
||||
import { validators } from '@agentic/platform-validators'
|
||||
import { relations } from '@fisch0920/drizzle-orm'
|
||||
import {
|
||||
boolean,
|
||||
|
@ -9,6 +9,15 @@ import {
|
|||
} from '@fisch0920/drizzle-orm/pg-core'
|
||||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
import {
|
||||
createInsertSchema,
|
||||
createSelectSchema,
|
||||
createUpdateSchema,
|
||||
cuid,
|
||||
deploymentId,
|
||||
projectId,
|
||||
timestamps
|
||||
} from './common'
|
||||
import { projects } from './project'
|
||||
import {
|
||||
type DeploymentOriginAdapter,
|
||||
|
@ -18,15 +27,6 @@ import {
|
|||
} from './schemas'
|
||||
import { teams, teamSelectSchema } from './team'
|
||||
import { users, userSelectSchema } from './user'
|
||||
import {
|
||||
createInsertSchema,
|
||||
createSelectSchema,
|
||||
createUpdateSchema,
|
||||
cuid,
|
||||
deploymentId,
|
||||
projectId,
|
||||
timestamps
|
||||
} from './utils'
|
||||
|
||||
export const deployments = pgTable(
|
||||
'deployments',
|
||||
|
@ -105,13 +105,6 @@ export const deploymentsRelations = relations(deployments, ({ one }) => ({
|
|||
})
|
||||
}))
|
||||
|
||||
export type DeploymentRelationFields = keyof ReturnType<
|
||||
(typeof deploymentsRelations)['config']
|
||||
>
|
||||
|
||||
export const deploymentRelationsSchema: z.ZodType<DeploymentRelationFields> =
|
||||
z.enum(['user', 'team', 'project'])
|
||||
|
||||
// TODO: virtual hasFreeTier
|
||||
// TODO: virtual url
|
||||
// TODO: virtual openApiUrl
|
|
@ -1,9 +1,8 @@
|
|||
export * from './common'
|
||||
export * from './consumer'
|
||||
export * from './deployment'
|
||||
export * from './log-entry'
|
||||
export * from './project'
|
||||
export * from './schemas'
|
||||
export * from './team'
|
||||
export * from './team-member'
|
||||
export * from './user'
|
||||
export * from './utils'
|
|
@ -2,10 +2,6 @@ import { relations } from '@fisch0920/drizzle-orm'
|
|||
import { index, jsonb, pgTable, text } from '@fisch0920/drizzle-orm/pg-core'
|
||||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
import { consumers, consumerSelectSchema } from './consumer'
|
||||
import { deployments, deploymentSelectSchema } from './deployment'
|
||||
import { projects, projectSelectSchema } from './project'
|
||||
import { users, userSelectSchema } from './user'
|
||||
import {
|
||||
createInsertSchema,
|
||||
createSelectSchema,
|
||||
|
@ -16,7 +12,11 @@ import {
|
|||
logEntryTypeEnum,
|
||||
projectId,
|
||||
timestamps
|
||||
} from './utils'
|
||||
} from './common'
|
||||
import { consumers, consumerSelectSchema } from './consumer'
|
||||
import { deployments, deploymentSelectSchema } from './deployment'
|
||||
import { projects, projectSelectSchema } from './project'
|
||||
import { users, userSelectSchema } from './user'
|
||||
|
||||
/**
|
||||
* A `LogEntry` is an internal audit log entry.
|
|
@ -1,4 +1,4 @@
|
|||
import { validators } from '@agentic/validators'
|
||||
import { validators } from '@agentic/platform-validators'
|
||||
import { relations } from '@fisch0920/drizzle-orm'
|
||||
import {
|
||||
boolean,
|
||||
|
@ -10,6 +10,18 @@ import {
|
|||
} from '@fisch0920/drizzle-orm/pg-core'
|
||||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
import {
|
||||
createInsertSchema,
|
||||
createSelectSchema,
|
||||
createUpdateSchema,
|
||||
cuid,
|
||||
deploymentId,
|
||||
pricingCurrencyEnum,
|
||||
pricingIntervalEnum,
|
||||
projectId,
|
||||
stripeId,
|
||||
timestamps
|
||||
} from './common'
|
||||
import { deployments, deploymentSelectSchema } from './deployment'
|
||||
import {
|
||||
pricingIntervalSchema,
|
||||
|
@ -22,18 +34,6 @@ import {
|
|||
} from './schemas'
|
||||
import { teams, teamSelectSchema } from './team'
|
||||
import { users, userSelectSchema } from './user'
|
||||
import {
|
||||
createInsertSchema,
|
||||
createSelectSchema,
|
||||
createUpdateSchema,
|
||||
cuid,
|
||||
deploymentId,
|
||||
pricingCurrencyEnum,
|
||||
pricingIntervalEnum,
|
||||
projectId,
|
||||
stripeId,
|
||||
timestamps
|
||||
} from './utils'
|
||||
|
||||
export const projects = pgTable(
|
||||
'projects',
|
||||
|
@ -157,17 +157,6 @@ export const projectsRelations = relations(projects, ({ one }) => ({
|
|||
// })
|
||||
}))
|
||||
|
||||
export type ProjectRelationFields = keyof ReturnType<
|
||||
(typeof projectsRelations)['config']
|
||||
>
|
||||
|
||||
export const projectRelationsSchema: z.ZodType<ProjectRelationFields> = z.enum([
|
||||
'user',
|
||||
'team',
|
||||
'lastPublishedDeployment',
|
||||
'lastDeployment'
|
||||
])
|
||||
|
||||
export const projectSelectSchema = createSelectSchema(projects, {
|
||||
applicationFeePercent: (schema) => schema.nonnegative(),
|
||||
|
|
@ -7,8 +7,6 @@ import {
|
|||
} from '@fisch0920/drizzle-orm/pg-core'
|
||||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
import { teams, teamSelectSchema } from './team'
|
||||
import { users, userSelectSchema } from './user'
|
||||
import {
|
||||
createInsertSchema,
|
||||
createSelectSchema,
|
||||
|
@ -18,7 +16,9 @@ import {
|
|||
teamSlug,
|
||||
timestamp,
|
||||
timestamps
|
||||
} from './utils'
|
||||
} from './common'
|
||||
import { teams, teamSelectSchema } from './team'
|
||||
import { users, userSelectSchema } from './user'
|
||||
|
||||
export const teamMembers = pgTable(
|
||||
'team_members',
|
|
@ -1,4 +1,4 @@
|
|||
import { validators } from '@agentic/validators'
|
||||
import { validators } from '@agentic/platform-validators'
|
||||
import { relations } from '@fisch0920/drizzle-orm'
|
||||
import {
|
||||
index,
|
||||
|
@ -8,8 +8,6 @@ import {
|
|||
} from '@fisch0920/drizzle-orm/pg-core'
|
||||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
import { teamMembers } from './team-member'
|
||||
import { users, userSelectSchema } from './user'
|
||||
import {
|
||||
createInsertSchema,
|
||||
createSelectSchema,
|
||||
|
@ -18,7 +16,9 @@ import {
|
|||
id,
|
||||
teamSlug,
|
||||
timestamps
|
||||
} from './utils'
|
||||
} from './common'
|
||||
import { teamMembers } from './team-member'
|
||||
import { users, userSelectSchema } from './user'
|
||||
|
||||
export const teams = pgTable(
|
||||
'teams',
|
|
@ -1,5 +1,5 @@
|
|||
import { sha256 } from '@agentic/platform-core'
|
||||
import { validators } from '@agentic/validators'
|
||||
import { validators } from '@agentic/platform-validators'
|
||||
import { relations } from '@fisch0920/drizzle-orm'
|
||||
import {
|
||||
boolean,
|
||||
|
@ -11,8 +11,6 @@ import {
|
|||
} from '@fisch0920/drizzle-orm/pg-core'
|
||||
import { hashSync } from 'bcryptjs'
|
||||
|
||||
import { type AuthProviders, publicAuthProvidersSchema } from './schemas'
|
||||
import { teams } from './team'
|
||||
import {
|
||||
createInsertSchema,
|
||||
createSelectSchema,
|
||||
|
@ -23,7 +21,9 @@ import {
|
|||
timestamps,
|
||||
username,
|
||||
userRoleEnum
|
||||
} from './utils'
|
||||
} from './common'
|
||||
import { type AuthProviders, publicAuthProvidersSchema } from './schemas'
|
||||
import { teams } from './team'
|
||||
|
||||
export const users = pgTable(
|
||||
'users',
|
|
@ -1,6 +1,10 @@
|
|||
import { validators } from '@agentic/validators'
|
||||
import { validators } from '@agentic/platform-validators'
|
||||
import { z } from '@hono/zod-openapi'
|
||||
|
||||
import type { consumersRelations } from './schema/consumer'
|
||||
import type { deploymentsRelations } from './schema/deployment'
|
||||
import type { projectsRelations } from './schema/project'
|
||||
|
||||
function getCuidSchema(idLabel: string) {
|
||||
return z.string().refine((id) => validators.cuid(id), {
|
||||
message: `Invalid ${idLabel}`
|
||||
|
@ -57,3 +61,25 @@ export const paginationSchema = z.object({
|
|||
// )
|
||||
// })
|
||||
// }
|
||||
|
||||
export type ProjectRelationFields = keyof ReturnType<
|
||||
(typeof projectsRelations)['config']
|
||||
>
|
||||
export const projectRelationsSchema: z.ZodType<ProjectRelationFields> = z.enum([
|
||||
'user',
|
||||
'team',
|
||||
'lastPublishedDeployment',
|
||||
'lastDeployment'
|
||||
])
|
||||
|
||||
export type DeploymentRelationFields = keyof ReturnType<
|
||||
(typeof deploymentsRelations)['config']
|
||||
>
|
||||
export const deploymentRelationsSchema: z.ZodType<DeploymentRelationFields> =
|
||||
z.enum(['user', 'team', 'project'])
|
||||
|
||||
export type ConsumerRelationFields = keyof ReturnType<
|
||||
(typeof consumersRelations)['config']
|
||||
>
|
||||
export const consumerRelationsSchema: z.ZodType<ConsumerRelationFields> =
|
||||
z.enum(['user', 'project', 'deployment'])
|
|
@ -1,7 +1,5 @@
|
|||
import { expectTypeOf, test } from 'vitest'
|
||||
|
||||
import type { LogLevel } from '@/lib/logger'
|
||||
|
||||
import type { LogEntry, RawLogEntry, RawUser, User } from './types'
|
||||
|
||||
type UserKeys = Exclude<keyof User & keyof RawUser, 'authProviders'>
|
||||
|
@ -19,6 +17,4 @@ test('LogEntry types are compatible', () => {
|
|||
expectTypeOf<LogEntry[LogEntryKeys]>().toEqualTypeOf<
|
||||
RawLogEntry[LogEntryKeys]
|
||||
>()
|
||||
|
||||
expectTypeOf<LogEntry['level']>().toEqualTypeOf<LogLevel>()
|
||||
})
|
|
@ -0,0 +1,91 @@
|
|||
import { hashObject } from '@agentic/platform-core'
|
||||
|
||||
import type {
|
||||
PricingInterval,
|
||||
PricingPlan,
|
||||
PricingPlanLineItem,
|
||||
PricingPlanList
|
||||
} from './schema/schemas'
|
||||
import type { RawProject } from './types'
|
||||
|
||||
/**
|
||||
* Gets the hash used to uniquely map a PricingPlanLineItem to its
|
||||
* corresponding Stripe Price in a stable way across deployments within a
|
||||
* project.
|
||||
*
|
||||
* This hash is used as the key for the `Project._stripePriceIdMap`.
|
||||
*/
|
||||
export function getPricingPlanLineItemHashForStripePrice({
|
||||
pricingPlan,
|
||||
pricingPlanLineItem,
|
||||
project
|
||||
}: {
|
||||
pricingPlan: PricingPlan
|
||||
pricingPlanLineItem: PricingPlanLineItem
|
||||
project: RawProject
|
||||
}) {
|
||||
// TODO: use pricingPlan.slug as well here?
|
||||
// TODO: not sure if this is needed or not...
|
||||
// With pricing plan slug:
|
||||
// - 'price:free:base:<hash>'
|
||||
// - 'price:basic-monthly:base:<hash>'
|
||||
// - 'price:basic-monthly:requests:<hash>'
|
||||
// Without pricing plan slug:
|
||||
// - 'price:base:<hash>'
|
||||
// - 'price:base:<hash>'
|
||||
// - 'price:requests:<hash>'
|
||||
|
||||
const hash = hashObject({
|
||||
...pricingPlanLineItem,
|
||||
projectId: project.id,
|
||||
stripeAccountId: project._stripeAccountId,
|
||||
currency: project.pricingCurrency
|
||||
})
|
||||
|
||||
return `price:${pricingPlan.slug}:${pricingPlanLineItem.slug}:${hash}`
|
||||
}
|
||||
|
||||
export function getStripePriceIdForPricingPlanLineItem({
|
||||
pricingPlan,
|
||||
pricingPlanLineItem,
|
||||
project
|
||||
}: {
|
||||
pricingPlan: PricingPlan
|
||||
pricingPlanLineItem: PricingPlanLineItem
|
||||
project: RawProject
|
||||
}): string | undefined {
|
||||
const pricingPlanLineItemHash = getPricingPlanLineItemHashForStripePrice({
|
||||
pricingPlan,
|
||||
pricingPlanLineItem,
|
||||
project
|
||||
})
|
||||
|
||||
return project._stripePriceIdMap[pricingPlanLineItemHash]
|
||||
}
|
||||
|
||||
export function getPricingPlansByInterval({
|
||||
pricingInterval,
|
||||
pricingPlans
|
||||
}: {
|
||||
pricingInterval: PricingInterval
|
||||
pricingPlans: PricingPlanList
|
||||
}): PricingPlan[] {
|
||||
return pricingPlans.filter(
|
||||
(pricingPlan) =>
|
||||
pricingPlan.interval === undefined ||
|
||||
pricingPlan.interval === pricingInterval
|
||||
)
|
||||
}
|
||||
|
||||
const pricingIntervalToLabelMap: Record<PricingInterval, string> = {
|
||||
day: 'daily',
|
||||
week: 'weekly',
|
||||
month: 'monthly',
|
||||
year: 'yearly'
|
||||
}
|
||||
|
||||
export function getLabelForPricingInterval(
|
||||
pricingInterval: PricingInterval
|
||||
): string {
|
||||
return pricingIntervalToLabelMap[pricingInterval]
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"extends": "@fisch0920/config/tsconfig-node",
|
||||
"include": ["src", "*.config.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@agentic/validators",
|
||||
"name": "@agentic/platform-validators",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"description": "Validation utils for the Agentic platform.",
|
||||
|
|
|
@ -128,15 +128,12 @@ importers:
|
|||
'@agentic/platform-core':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/core
|
||||
'@agentic/validators':
|
||||
'@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)(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)(postgres@3.4.5))(zod@3.24.4)
|
||||
'@hono/node-server':
|
||||
specifier: ^1.14.1
|
||||
version: 1.14.1(hono@4.7.9)
|
||||
|
@ -146,21 +143,12 @@ importers:
|
|||
'@hono/zod-openapi':
|
||||
specifier: ^0.19.6
|
||||
version: 0.19.6(hono@4.7.9)(zod@3.24.4)
|
||||
'@hono/zod-validator':
|
||||
specifier: ^0.5.0
|
||||
version: 0.5.0(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)
|
||||
'@sentry/node':
|
||||
specifier: ^9.19.0
|
||||
version: 9.19.0
|
||||
bcryptjs:
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2
|
||||
eventid:
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1
|
||||
|
@ -179,9 +167,6 @@ 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
|
||||
|
@ -238,6 +223,9 @@ importers:
|
|||
'@agentic/platform-api':
|
||||
specifier: workspace:*
|
||||
version: link:../../apps/api
|
||||
'@agentic/platform-db':
|
||||
specifier: workspace:*
|
||||
version: link:../db
|
||||
'@commander-js/extra-typings':
|
||||
specifier: ^14.0.0
|
||||
version: 14.0.0(commander@14.0.0)
|
||||
|
@ -258,6 +246,45 @@ 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)(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)(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':
|
||||
|
|
Ładowanie…
Reference in New Issue