kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: add private/public to projects and expose public projects for marketplace
rodzic
844453584a
commit
ee5783e780
|
@ -4,7 +4,7 @@ import { assert } from '@agentic/platform-core'
|
||||||
|
|
||||||
import { authStorage } from './utils'
|
import { authStorage } from './utils'
|
||||||
|
|
||||||
export function registerV1AuthGitHubOAuthCallback(
|
export function registerV1GitHubOAuthCallback(
|
||||||
app: OpenAPIHono<DefaultHonoEnv>
|
app: OpenAPIHono<DefaultHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.get('auth/github/callback', async (c) => {
|
return app.get('auth/github/callback', async (c) => {
|
||||||
|
|
|
@ -51,7 +51,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1AuthGitHubOAuthExchange(
|
export function registerV1GitHubOAuthExchange(
|
||||||
app: OpenAPIHono<DefaultHonoEnv>
|
app: OpenAPIHono<DefaultHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -35,7 +35,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1AuthGitHubOAuthInitFlow(
|
export function registerV1GitHubOAuthInitFlow(
|
||||||
app: OpenAPIHono<DefaultHonoEnv>
|
app: OpenAPIHono<DefaultHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -49,9 +49,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1AuthSignInWithPassword(
|
export function registerV1SignInWithPassword(app: OpenAPIHono<DefaultHonoEnv>) {
|
||||||
app: OpenAPIHono<DefaultHonoEnv>
|
|
||||||
) {
|
|
||||||
return app.openapi(route, trySignIn)
|
return app.openapi(route, trySignIn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,9 +52,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1AuthSignUpWithPassword(
|
export function registerV1SignUpWithPassword(app: OpenAPIHono<DefaultHonoEnv>) {
|
||||||
app: OpenAPIHono<DefaultHonoEnv>
|
|
||||||
) {
|
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
try {
|
try {
|
||||||
// try signing in to see if the user already exists
|
// try signing in to see if the user already exists
|
||||||
|
|
|
@ -42,7 +42,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1AdminConsumersActivateConsumer(
|
export function registerV1AdminActivateConsumer(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -38,7 +38,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1AdminConsumersGetConsumerByToken(
|
export function registerV1AdminGetConsumerByToken(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -45,7 +45,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1ConsumersCreateConsumer(
|
export function registerV1CreateConsumer(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -37,9 +37,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1ConsumersGetConsumer(
|
export function registerV1GetConsumer(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
|
||||||
) {
|
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
const { consumerId } = c.req.valid('param')
|
const { consumerId } = c.req.valid('param')
|
||||||
const { populate = [] } = c.req.valid('query')
|
const { populate = [] } = c.req.valid('query')
|
||||||
|
|
|
@ -36,7 +36,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1ConsumersListConsumers(
|
export function registerV1ListConsumers(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -38,7 +38,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1ConsumersListForProject(
|
export function registerV1ListConsumersForProject(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -37,7 +37,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1ConsumersRefreshConsumerToken(
|
export function registerV1RefreshConsumerToken(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -49,7 +49,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1ConsumersUpdateConsumer(
|
export function registerV1UpdateConsumer(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -39,7 +39,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1AdminDeploymentsGetDeploymentByIdentifier(
|
export function registerV1AdminGetDeploymentByIdentifier(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { resolveAgenticProjectConfig } from '@agentic/platform'
|
||||||
import { assert, parseZodSchema, sha256 } from '@agentic/platform-core'
|
import { assert, parseZodSchema, sha256 } from '@agentic/platform-core'
|
||||||
import {
|
import {
|
||||||
isValidDeploymentIdentifier,
|
isValidDeploymentIdentifier,
|
||||||
isValidProjectIdentifier
|
parseProjectIdentifier
|
||||||
} from '@agentic/platform-validators'
|
} from '@agentic/platform-validators'
|
||||||
import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
|
import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1DeploymentsCreateDeployment(
|
export function registerV1CreateDeployment(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
@ -64,13 +64,10 @@ export function registerV1DeploymentsCreateDeployment(
|
||||||
const teamMember = c.get('teamMember')
|
const teamMember = c.get('teamMember')
|
||||||
const logger = c.get('logger')
|
const logger = c.get('logger')
|
||||||
|
|
||||||
const namespace = teamMember ? teamMember.teamSlug : user.username
|
const inputNamespace = teamMember ? teamMember.teamSlug : user.username
|
||||||
const projectIdentifier = `@${namespace}/${body.name}`
|
const inputProjectIdentifier = `@${inputNamespace}/${body.name}`
|
||||||
assert(
|
const { projectIdentifier, projectNamespace, projectName } =
|
||||||
isValidProjectIdentifier(projectIdentifier),
|
parseProjectIdentifier(inputProjectIdentifier)
|
||||||
400,
|
|
||||||
`Invalid project identifier "${projectIdentifier}"`
|
|
||||||
)
|
|
||||||
|
|
||||||
let project = await db.query.projects.findFirst({
|
let project = await db.query.projects.findFirst({
|
||||||
where: eq(schema.projects.identifier, projectIdentifier),
|
where: eq(schema.projects.identifier, projectIdentifier),
|
||||||
|
@ -88,8 +85,9 @@ export function registerV1DeploymentsCreateDeployment(
|
||||||
await db
|
await db
|
||||||
.insert(schema.projects)
|
.insert(schema.projects)
|
||||||
.values({
|
.values({
|
||||||
name: body.name,
|
|
||||||
identifier: projectIdentifier,
|
identifier: projectIdentifier,
|
||||||
|
namespace: projectNamespace,
|
||||||
|
name: projectName,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
teamId: teamMember?.teamId,
|
teamId: teamMember?.teamId,
|
||||||
_secret: await sha256()
|
_secret: await sha256()
|
||||||
|
|
|
@ -37,7 +37,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1DeploymentsGetDeploymentByIdentifier(
|
export function registerV1GetDeploymentByIdentifier(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -38,7 +38,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1DeploymentsGetDeployment(
|
export function registerV1GetDeployment(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -37,7 +37,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1DeploymentsListDeployments(
|
export function registerV1ListDeployments(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -46,7 +46,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1DeploymentsPublishDeployment(
|
export function registerV1PublishDeployment(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -45,7 +45,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1DeploymentsUpdateDeployment(
|
export function registerV1UpdateDeployment(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -6,42 +6,45 @@ import type { AuthenticatedHonoEnv } from '@/lib/types'
|
||||||
import * as middleware from '@/lib/middleware'
|
import * as middleware from '@/lib/middleware'
|
||||||
import { registerOpenAPIErrorResponses } from '@/lib/openapi-utils'
|
import { registerOpenAPIErrorResponses } from '@/lib/openapi-utils'
|
||||||
|
|
||||||
import { registerV1AuthGitHubOAuthCallback } from './auth/github-callback'
|
import { registerV1GitHubOAuthCallback } from './auth/github-callback'
|
||||||
import { registerV1AuthGitHubOAuthExchange } from './auth/github-exchange'
|
import { registerV1GitHubOAuthExchange } from './auth/github-exchange'
|
||||||
import { registerV1AuthGitHubOAuthInitFlow } from './auth/github-init'
|
import { registerV1GitHubOAuthInitFlow } from './auth/github-init'
|
||||||
import { registerV1AuthSignInWithPassword } from './auth/sign-in-with-password'
|
import { registerV1SignInWithPassword } from './auth/sign-in-with-password'
|
||||||
import { registerV1AuthSignUpWithPassword } from './auth/sign-up-with-password'
|
import { registerV1SignUpWithPassword } from './auth/sign-up-with-password'
|
||||||
import { registerV1AdminConsumersActivateConsumer } from './consumers/admin-activate-consumer'
|
import { registerV1AdminActivateConsumer } from './consumers/admin-activate-consumer'
|
||||||
import { registerV1AdminConsumersGetConsumerByToken } from './consumers/admin-get-consumer-by-token'
|
import { registerV1AdminGetConsumerByToken } from './consumers/admin-get-consumer-by-token'
|
||||||
import { registerV1ConsumersCreateConsumer } from './consumers/create-consumer'
|
import { registerV1CreateConsumer } from './consumers/create-consumer'
|
||||||
import { registerV1ConsumersGetConsumer } from './consumers/get-consumer'
|
import { registerV1GetConsumer } from './consumers/get-consumer'
|
||||||
import { registerV1ConsumersListConsumers } from './consumers/list-consumers'
|
import { registerV1ListConsumers } from './consumers/list-consumers'
|
||||||
import { registerV1ConsumersListForProject } from './consumers/list-project-consumers'
|
import { registerV1ListConsumersForProject } from './consumers/list-project-consumers'
|
||||||
import { registerV1ConsumersRefreshConsumerToken } from './consumers/refresh-consumer-token'
|
import { registerV1RefreshConsumerToken } from './consumers/refresh-consumer-token'
|
||||||
import { registerV1ConsumersUpdateConsumer } from './consumers/update-consumer'
|
import { registerV1UpdateConsumer } from './consumers/update-consumer'
|
||||||
import { registerV1AdminDeploymentsGetDeploymentByIdentifier } from './deployments/admin-get-deployment-by-identifier'
|
import { registerV1AdminGetDeploymentByIdentifier } from './deployments/admin-get-deployment-by-identifier'
|
||||||
import { registerV1DeploymentsCreateDeployment } from './deployments/create-deployment'
|
import { registerV1CreateDeployment } from './deployments/create-deployment'
|
||||||
import { registerV1DeploymentsGetDeployment } from './deployments/get-deployment'
|
import { registerV1GetDeployment } from './deployments/get-deployment'
|
||||||
import { registerV1DeploymentsGetDeploymentByIdentifier } from './deployments/get-deployment-by-identifier'
|
import { registerV1GetDeploymentByIdentifier } from './deployments/get-deployment-by-identifier'
|
||||||
import { registerV1DeploymentsListDeployments } from './deployments/list-deployments'
|
import { registerV1ListDeployments } from './deployments/list-deployments'
|
||||||
import { registerV1DeploymentsPublishDeployment } from './deployments/publish-deployment'
|
import { registerV1PublishDeployment } from './deployments/publish-deployment'
|
||||||
import { registerV1DeploymentsUpdateDeployment } from './deployments/update-deployment'
|
import { registerV1UpdateDeployment } from './deployments/update-deployment'
|
||||||
import { registerHealthCheck } from './health-check'
|
import { registerHealthCheck } from './health-check'
|
||||||
import { registerV1ProjectsCreateProject } from './projects/create-project'
|
import { registerV1CreateProject } from './projects/create-project'
|
||||||
import { registerV1ProjectsGetProject } from './projects/get-project'
|
import { registerV1GetProject } from './projects/get-project'
|
||||||
import { registerV1ProjectsGetProjectByIdentifier } from './projects/get-project-by-identifier'
|
import { registerV1GetProjectByIdentifier } from './projects/get-project-by-identifier'
|
||||||
import { registerV1ProjectsListProjects } from './projects/list-projects'
|
import { registerV1GetPublicProject } from './projects/get-public-project'
|
||||||
import { registerV1ProjectsUpdateProject } from './projects/update-project'
|
import { registerV1GetPublicProjectByIdentifier } from './projects/get-public-project-by-identifier'
|
||||||
import { registerV1TeamsCreateTeam } from './teams/create-team'
|
import { registerV1ListProjects } from './projects/list-projects'
|
||||||
import { registerV1TeamsDeleteTeam } from './teams/delete-team'
|
import { registerV1ListPublicProjects } from './projects/list-public-projects'
|
||||||
import { registerV1TeamsGetTeam } from './teams/get-team'
|
import { registerV1UpdateProject } from './projects/update-project'
|
||||||
import { registerV1TeamsListTeams } from './teams/list-teams'
|
import { registerV1CreateTeam } from './teams/create-team'
|
||||||
import { registerV1TeamsMembersCreateTeamMember } from './teams/members/create-team-member'
|
import { registerV1DeleteTeam } from './teams/delete-team'
|
||||||
import { registerV1TeamsMembersDeleteTeamMember } from './teams/members/delete-team-member'
|
import { registerV1GetTeam } from './teams/get-team'
|
||||||
import { registerV1TeamsMembersUpdateTeamMember } from './teams/members/update-team-member'
|
import { registerV1ListTeams } from './teams/list-teams'
|
||||||
import { registerV1TeamsUpdateTeam } from './teams/update-team'
|
import { registerV1CreateTeamMember } from './teams/members/create-team-member'
|
||||||
import { registerV1UsersGetUser } from './users/get-user'
|
import { registerV1DeleteTeamMember } from './teams/members/delete-team-member'
|
||||||
import { registerV1UsersUpdateUser } from './users/update-user'
|
import { registerV1UpdateTeamMember } from './teams/members/update-team-member'
|
||||||
|
import { registerV1UpdateTeam } from './teams/update-team'
|
||||||
|
import { registerV1GetUser } from './users/get-user'
|
||||||
|
import { registerV1UpdateUser } from './users/update-user'
|
||||||
import { registerV1StripeWebhook } from './webhooks/stripe-webhook'
|
import { registerV1StripeWebhook } from './webhooks/stripe-webhook'
|
||||||
|
|
||||||
// Note that the order of some of these routes is important because of
|
// Note that the order of some of these routes is important because of
|
||||||
|
@ -79,55 +82,60 @@ const privateRouter = new OpenAPIHono<AuthenticatedHonoEnv>()
|
||||||
registerHealthCheck(publicRouter)
|
registerHealthCheck(publicRouter)
|
||||||
|
|
||||||
// Auth
|
// Auth
|
||||||
registerV1AuthSignInWithPassword(publicRouter)
|
registerV1SignInWithPassword(publicRouter)
|
||||||
registerV1AuthSignUpWithPassword(publicRouter)
|
registerV1SignUpWithPassword(publicRouter)
|
||||||
registerV1AuthGitHubOAuthExchange(publicRouter)
|
registerV1GitHubOAuthExchange(publicRouter)
|
||||||
registerV1AuthGitHubOAuthInitFlow(publicRouter)
|
registerV1GitHubOAuthInitFlow(publicRouter)
|
||||||
registerV1AuthGitHubOAuthCallback(publicRouter)
|
registerV1GitHubOAuthCallback(publicRouter)
|
||||||
|
|
||||||
// Users
|
// Users
|
||||||
registerV1UsersGetUser(privateRouter)
|
registerV1GetUser(privateRouter)
|
||||||
registerV1UsersUpdateUser(privateRouter)
|
registerV1UpdateUser(privateRouter)
|
||||||
|
|
||||||
// Teams
|
// Teams
|
||||||
registerV1TeamsCreateTeam(privateRouter)
|
registerV1CreateTeam(privateRouter)
|
||||||
registerV1TeamsListTeams(privateRouter)
|
registerV1ListTeams(privateRouter)
|
||||||
registerV1TeamsGetTeam(privateRouter)
|
registerV1GetTeam(privateRouter)
|
||||||
registerV1TeamsDeleteTeam(privateRouter)
|
registerV1DeleteTeam(privateRouter)
|
||||||
registerV1TeamsUpdateTeam(privateRouter)
|
registerV1UpdateTeam(privateRouter)
|
||||||
|
|
||||||
// Team members
|
// Team members
|
||||||
registerV1TeamsMembersCreateTeamMember(privateRouter)
|
registerV1CreateTeamMember(privateRouter)
|
||||||
registerV1TeamsMembersUpdateTeamMember(privateRouter)
|
registerV1UpdateTeamMember(privateRouter)
|
||||||
registerV1TeamsMembersDeleteTeamMember(privateRouter)
|
registerV1DeleteTeamMember(privateRouter)
|
||||||
|
|
||||||
// Projects
|
// Public projects
|
||||||
registerV1ProjectsCreateProject(privateRouter)
|
registerV1ListPublicProjects(publicRouter)
|
||||||
registerV1ProjectsListProjects(privateRouter)
|
registerV1GetPublicProjectByIdentifier(publicRouter) // must be before `registerV1GetPublicProject`
|
||||||
registerV1ProjectsGetProjectByIdentifier(privateRouter) // must be before `registerV1ProjectsGetProject`
|
registerV1GetPublicProject(publicRouter)
|
||||||
registerV1ProjectsGetProject(privateRouter)
|
|
||||||
registerV1ProjectsUpdateProject(privateRouter)
|
// Private projects
|
||||||
|
registerV1CreateProject(privateRouter)
|
||||||
|
registerV1ListProjects(privateRouter)
|
||||||
|
registerV1GetProjectByIdentifier(privateRouter) // must be before `registerV1GetProject`
|
||||||
|
registerV1GetProject(privateRouter)
|
||||||
|
registerV1UpdateProject(privateRouter)
|
||||||
|
|
||||||
// Consumers
|
// Consumers
|
||||||
registerV1ConsumersGetConsumer(privateRouter)
|
registerV1GetConsumer(privateRouter)
|
||||||
registerV1ConsumersCreateConsumer(privateRouter)
|
registerV1CreateConsumer(privateRouter)
|
||||||
registerV1ConsumersUpdateConsumer(privateRouter)
|
registerV1UpdateConsumer(privateRouter)
|
||||||
registerV1ConsumersRefreshConsumerToken(privateRouter)
|
registerV1RefreshConsumerToken(privateRouter)
|
||||||
registerV1ConsumersListConsumers(privateRouter)
|
registerV1ListConsumers(privateRouter)
|
||||||
registerV1ConsumersListForProject(privateRouter)
|
registerV1ListConsumersForProject(privateRouter)
|
||||||
|
|
||||||
// Deployments
|
// Deployments
|
||||||
registerV1DeploymentsGetDeploymentByIdentifier(privateRouter) // must be before `registerV1DeploymentsGetDeployment`
|
registerV1GetDeploymentByIdentifier(privateRouter) // must be before `registerV1GetDeployment`
|
||||||
registerV1DeploymentsGetDeployment(privateRouter)
|
registerV1GetDeployment(privateRouter)
|
||||||
registerV1DeploymentsCreateDeployment(privateRouter)
|
registerV1CreateDeployment(privateRouter)
|
||||||
registerV1DeploymentsUpdateDeployment(privateRouter)
|
registerV1UpdateDeployment(privateRouter)
|
||||||
registerV1DeploymentsListDeployments(privateRouter)
|
registerV1ListDeployments(privateRouter)
|
||||||
registerV1DeploymentsPublishDeployment(privateRouter)
|
registerV1PublishDeployment(privateRouter)
|
||||||
|
|
||||||
// Internal admin routes
|
// Internal admin routes
|
||||||
registerV1AdminConsumersGetConsumerByToken(privateRouter)
|
registerV1AdminGetConsumerByToken(privateRouter)
|
||||||
registerV1AdminConsumersActivateConsumer(privateRouter)
|
registerV1AdminActivateConsumer(privateRouter)
|
||||||
registerV1AdminDeploymentsGetDeploymentByIdentifier(privateRouter)
|
registerV1AdminGetDeploymentByIdentifier(privateRouter)
|
||||||
|
|
||||||
// Webhook event handlers
|
// Webhook event handlers
|
||||||
registerV1StripeWebhook(publicRouter)
|
registerV1StripeWebhook(publicRouter)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { assert, parseZodSchema, sha256 } from '@agentic/platform-core'
|
import { assert, parseZodSchema, sha256 } from '@agentic/platform-core'
|
||||||
import { isValidProjectIdentifier } from '@agentic/platform-validators'
|
import { parseProjectIdentifier } from '@agentic/platform-validators'
|
||||||
import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
|
import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
|
||||||
|
|
||||||
import type { AuthenticatedHonoEnv } from '@/lib/types'
|
import type { AuthenticatedHonoEnv } from '@/lib/types'
|
||||||
|
@ -40,7 +40,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1ProjectsCreateProject(
|
export function registerV1CreateProject(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
@ -54,8 +54,9 @@ export function registerV1ProjectsCreateProject(
|
||||||
const teamMember = c.get('teamMember')
|
const teamMember = c.get('teamMember')
|
||||||
const namespace = teamMember ? teamMember.teamSlug : user.username
|
const namespace = teamMember ? teamMember.teamSlug : user.username
|
||||||
const identifier = `@${namespace}/${body.name}`
|
const identifier = `@${namespace}/${body.name}`
|
||||||
|
const parsedProjectIdentifier = parseProjectIdentifier(identifier)
|
||||||
assert(
|
assert(
|
||||||
isValidProjectIdentifier(identifier),
|
parsedProjectIdentifier,
|
||||||
400,
|
400,
|
||||||
`Invalid project identifier "${identifier}"`
|
`Invalid project identifier "${identifier}"`
|
||||||
)
|
)
|
||||||
|
@ -64,7 +65,9 @@ export function registerV1ProjectsCreateProject(
|
||||||
.insert(schema.projects)
|
.insert(schema.projects)
|
||||||
.values({
|
.values({
|
||||||
...body,
|
...body,
|
||||||
identifier,
|
identifier: parsedProjectIdentifier.projectIdentifier,
|
||||||
|
namespace: parsedProjectIdentifier.projectNamespace,
|
||||||
|
name: parsedProjectIdentifier.projectName,
|
||||||
teamId: teamMember?.teamId,
|
teamId: teamMember?.teamId,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
_secret: await sha256()
|
_secret: await sha256()
|
||||||
|
|
|
@ -37,7 +37,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1ProjectsGetProjectByIdentifier(
|
export function registerV1GetProjectByIdentifier(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -37,9 +37,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1ProjectsGetProject(
|
export function registerV1GetProject(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
|
||||||
) {
|
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
const { projectId } = c.req.valid('param')
|
const { projectId } = c.req.valid('param')
|
||||||
const { populate = [] } = c.req.valid('query')
|
const { populate = [] } = c.req.valid('query')
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import type { DefaultHonoEnv } from '@agentic/platform-hono'
|
||||||
|
import { assert, parseZodSchema } from '@agentic/platform-core'
|
||||||
|
import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
|
||||||
|
|
||||||
|
import { db, eq, schema } from '@/db'
|
||||||
|
import {
|
||||||
|
openapiAuthenticatedSecuritySchemas,
|
||||||
|
openapiErrorResponse404,
|
||||||
|
openapiErrorResponses
|
||||||
|
} from '@/lib/openapi-utils'
|
||||||
|
|
||||||
|
import { projectIdentifierAndPopulateSchema } from './schemas'
|
||||||
|
|
||||||
|
const route = createRoute({
|
||||||
|
description:
|
||||||
|
'Gets a public project by its public identifier (eg, "@username/project-name").',
|
||||||
|
tags: ['projects'],
|
||||||
|
operationId: 'getPublicProjectByIdentifier',
|
||||||
|
method: 'get',
|
||||||
|
path: 'projects/public/by-identifier',
|
||||||
|
security: openapiAuthenticatedSecuritySchemas,
|
||||||
|
request: {
|
||||||
|
query: projectIdentifierAndPopulateSchema
|
||||||
|
},
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: 'A project',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: schema.projectSelectSchema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...openapiErrorResponses,
|
||||||
|
...openapiErrorResponse404
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export function registerV1GetPublicProjectByIdentifier(
|
||||||
|
app: OpenAPIHono<DefaultHonoEnv>
|
||||||
|
) {
|
||||||
|
return app.openapi(route, async (c) => {
|
||||||
|
const { projectIdentifier, populate = [] } = c.req.valid('query')
|
||||||
|
|
||||||
|
const project = await db.query.projects.findFirst({
|
||||||
|
where: eq(schema.projects.identifier, projectIdentifier),
|
||||||
|
with: {
|
||||||
|
lastPublishedDeployment: true,
|
||||||
|
...Object.fromEntries(populate.map((field) => [field, true]))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
assert(
|
||||||
|
project && project.private && project.lastPublishedDeploymentId,
|
||||||
|
404,
|
||||||
|
`Public project not found "${projectIdentifier}"`
|
||||||
|
)
|
||||||
|
|
||||||
|
return c.json(parseZodSchema(schema.projectSelectSchema, project))
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
import type { DefaultHonoEnv } from '@agentic/platform-hono'
|
||||||
|
import { assert, parseZodSchema } from '@agentic/platform-core'
|
||||||
|
import { createRoute, type OpenAPIHono } from '@hono/zod-openapi'
|
||||||
|
|
||||||
|
import { db, eq, schema } from '@/db'
|
||||||
|
import {
|
||||||
|
openapiAuthenticatedSecuritySchemas,
|
||||||
|
openapiErrorResponse404,
|
||||||
|
openapiErrorResponses
|
||||||
|
} from '@/lib/openapi-utils'
|
||||||
|
|
||||||
|
import { populateProjectSchema, projectIdParamsSchema } from './schemas'
|
||||||
|
|
||||||
|
const route = createRoute({
|
||||||
|
description: 'Gets a public project by ID.',
|
||||||
|
tags: ['projects'],
|
||||||
|
operationId: 'getPublicProject',
|
||||||
|
method: 'get',
|
||||||
|
path: 'projects/public/{projectId}',
|
||||||
|
security: openapiAuthenticatedSecuritySchemas,
|
||||||
|
request: {
|
||||||
|
params: projectIdParamsSchema,
|
||||||
|
query: populateProjectSchema
|
||||||
|
},
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: 'A project',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: schema.projectSelectSchema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...openapiErrorResponses,
|
||||||
|
...openapiErrorResponse404
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export function registerV1GetPublicProject(app: OpenAPIHono<DefaultHonoEnv>) {
|
||||||
|
return app.openapi(route, async (c) => {
|
||||||
|
const { projectId } = c.req.valid('param')
|
||||||
|
const { populate = [] } = c.req.valid('query')
|
||||||
|
|
||||||
|
const project = await db.query.projects.findFirst({
|
||||||
|
where: eq(schema.projects.id, projectId),
|
||||||
|
with: {
|
||||||
|
lastPublishedDeployment: true,
|
||||||
|
...Object.fromEntries(populate.map((field) => [field, true]))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
assert(
|
||||||
|
project && project.private && project.lastPublishedDeploymentId,
|
||||||
|
404,
|
||||||
|
`Public project not found "${projectId}"`
|
||||||
|
)
|
||||||
|
|
||||||
|
return c.json(parseZodSchema(schema.projectSelectSchema, project))
|
||||||
|
})
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ import {
|
||||||
import { paginationAndPopulateProjectSchema } from './schemas'
|
import { paginationAndPopulateProjectSchema } from './schemas'
|
||||||
|
|
||||||
const route = createRoute({
|
const route = createRoute({
|
||||||
description: 'Lists projects the authenticated user has access to.',
|
description: 'Lists projects owned by the authenticated user or team.',
|
||||||
tags: ['projects'],
|
tags: ['projects'],
|
||||||
operationId: 'listProjects',
|
operationId: 'listProjects',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
@ -34,9 +34,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1ProjectsListProjects(
|
export function registerV1ListProjects(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
|
||||||
) {
|
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
const {
|
const {
|
||||||
offset = 0,
|
offset = 0,
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
import type { DefaultHonoEnv } from '@agentic/platform-hono'
|
||||||
|
import { parseZodSchema } from '@agentic/platform-core'
|
||||||
|
import { createRoute, type OpenAPIHono, z } from '@hono/zod-openapi'
|
||||||
|
|
||||||
|
import { and, db, eq, isNotNull, schema } from '@/db'
|
||||||
|
import {
|
||||||
|
openapiAuthenticatedSecuritySchemas,
|
||||||
|
openapiErrorResponses
|
||||||
|
} from '@/lib/openapi-utils'
|
||||||
|
|
||||||
|
import { paginationAndPopulateProjectSchema } from './schemas'
|
||||||
|
|
||||||
|
const route = createRoute({
|
||||||
|
description:
|
||||||
|
'Lists projects that have been published publicly to the marketplace.',
|
||||||
|
tags: ['projects'],
|
||||||
|
operationId: 'listPublicProjects',
|
||||||
|
method: 'get',
|
||||||
|
path: 'projects/public',
|
||||||
|
security: openapiAuthenticatedSecuritySchemas,
|
||||||
|
request: {
|
||||||
|
query: paginationAndPopulateProjectSchema
|
||||||
|
},
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: 'A list of projects',
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: z.array(schema.projectSelectSchema)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...openapiErrorResponses
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export function registerV1ListPublicProjects(app: OpenAPIHono<DefaultHonoEnv>) {
|
||||||
|
return app.openapi(route, async (c) => {
|
||||||
|
const {
|
||||||
|
offset = 0,
|
||||||
|
limit = 10,
|
||||||
|
sort = 'desc',
|
||||||
|
sortBy = 'createdAt',
|
||||||
|
populate = []
|
||||||
|
} = c.req.valid('query')
|
||||||
|
|
||||||
|
const projects = await db.query.projects.findMany({
|
||||||
|
// List projects that are not private and have at least one published deployment
|
||||||
|
where: and(
|
||||||
|
eq(schema.projects.private, false),
|
||||||
|
isNotNull(schema.projects.lastPublishedDeploymentId)
|
||||||
|
),
|
||||||
|
with: {
|
||||||
|
lastPublishedDeployment: true,
|
||||||
|
...Object.fromEntries(populate.map((field) => [field, true]))
|
||||||
|
},
|
||||||
|
orderBy: (projects, { asc, desc }) => [
|
||||||
|
sort === 'desc' ? desc(projects[sortBy]) : asc(projects[sortBy])
|
||||||
|
],
|
||||||
|
offset,
|
||||||
|
limit
|
||||||
|
})
|
||||||
|
|
||||||
|
return c.json(parseZodSchema(z.array(schema.projectSelectSchema), projects))
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
// import { isValidNamespace } from '@agentic/platform-validators'
|
||||||
import { z } from '@hono/zod-openapi'
|
import { z } from '@hono/zod-openapi'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -17,6 +18,21 @@ export const projectIdParamsSchema = z.object({
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// export const namespaceParamsSchema = z.object({
|
||||||
|
// namespace: z
|
||||||
|
// .string()
|
||||||
|
// .refine((namespace) => isValidNamespace(namespace), {
|
||||||
|
// message: 'Invalid namespace'
|
||||||
|
// })
|
||||||
|
// .openapi({
|
||||||
|
// param: {
|
||||||
|
// description: 'Namespace',
|
||||||
|
// name: 'namespace',
|
||||||
|
// in: 'path'
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
|
||||||
export const projectIdentifierQuerySchema = z.object({
|
export const projectIdentifierQuerySchema = z.object({
|
||||||
projectIdentifier: projectIdentifierSchema
|
projectIdentifier: projectIdentifierSchema
|
||||||
})
|
})
|
||||||
|
|
|
@ -44,7 +44,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1ProjectsUpdateProject(
|
export function registerV1UpdateProject(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -40,9 +40,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1TeamsCreateTeam(
|
export function registerV1CreateTeam(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
|
||||||
) {
|
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
const user = await ensureAuthUser(c)
|
const user = await ensureAuthUser(c)
|
||||||
const body = c.req.valid('json')
|
const body = c.req.valid('json')
|
||||||
|
|
|
@ -36,9 +36,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1TeamsDeleteTeam(
|
export function registerV1DeleteTeam(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
|
||||||
) {
|
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
const { teamId } = c.req.valid('param')
|
const { teamId } = c.req.valid('param')
|
||||||
await aclTeamAdmin(c, { teamId })
|
await aclTeamAdmin(c, { teamId })
|
||||||
|
|
|
@ -36,7 +36,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1TeamsGetTeam(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
export function registerV1GetTeam(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
const { teamId } = c.req.valid('param')
|
const { teamId } = c.req.valid('param')
|
||||||
await aclTeamMember(c, { teamId })
|
await aclTeamMember(c, { teamId })
|
||||||
|
|
|
@ -31,9 +31,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1TeamsListTeams(
|
export function registerV1ListTeams(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
|
||||||
) {
|
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
const {
|
const {
|
||||||
offset = 0,
|
offset = 0,
|
||||||
|
|
|
@ -46,7 +46,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1TeamsMembersCreateTeamMember(
|
export function registerV1CreateTeamMember(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -37,7 +37,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1TeamsMembersDeleteTeamMember(
|
export function registerV1DeleteTeamMember(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -45,7 +45,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1TeamsMembersUpdateTeamMember(
|
export function registerV1UpdateTeamMember(
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
app: OpenAPIHono<AuthenticatedHonoEnv>
|
||||||
) {
|
) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
|
|
|
@ -44,9 +44,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1TeamsUpdateTeam(
|
export function registerV1UpdateTeam(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
|
||||||
) {
|
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
const { teamId } = c.req.valid('param')
|
const { teamId } = c.req.valid('param')
|
||||||
const body = c.req.valid('json')
|
const body = c.req.valid('json')
|
||||||
|
|
|
@ -36,7 +36,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1UsersGetUser(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
export function registerV1GetUser(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
const { userId } = c.req.valid('param')
|
const { userId } = c.req.valid('param')
|
||||||
await acl(c, { userId }, { label: 'User' })
|
await acl(c, { userId }, { label: 'User' })
|
||||||
|
|
|
@ -44,9 +44,7 @@ const route = createRoute({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerV1UsersUpdateUser(
|
export function registerV1UpdateUser(app: OpenAPIHono<AuthenticatedHonoEnv>) {
|
||||||
app: OpenAPIHono<AuthenticatedHonoEnv>
|
|
||||||
) {
|
|
||||||
return app.openapi(route, async (c) => {
|
return app.openapi(route, async (c) => {
|
||||||
const { userId } = c.req.valid('param')
|
const { userId } = c.req.valid('param')
|
||||||
await acl(c, { userId }, { label: 'User' })
|
await acl(c, { userId }, { label: 'User' })
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
import { isValidProjectName } from '@agentic/platform-validators'
|
import { isValidProjectName } from '@agentic/platform-validators'
|
||||||
import { relations } from '@fisch0920/drizzle-orm'
|
import { relations } from '@fisch0920/drizzle-orm'
|
||||||
import {
|
import {
|
||||||
|
boolean,
|
||||||
index,
|
index,
|
||||||
integer,
|
integer,
|
||||||
jsonb,
|
jsonb,
|
||||||
|
@ -62,8 +63,16 @@ export const projects = pgTable(
|
||||||
...timestamps,
|
...timestamps,
|
||||||
|
|
||||||
identifier: projectIdentifier().unique().notNull(),
|
identifier: projectIdentifier().unique().notNull(),
|
||||||
|
namespace: text().notNull(),
|
||||||
name: text().notNull(),
|
name: text().notNull(),
|
||||||
alias: text(),
|
|
||||||
|
// Defaulting to `true` for now to hide all projects from the marketplace
|
||||||
|
// by default. Will need to manually set to `true` to allow projects to be
|
||||||
|
// visible on the marketplace.
|
||||||
|
private: boolean().default(true).notNull(),
|
||||||
|
|
||||||
|
// TODO: allow for multiple aliases like vercel
|
||||||
|
// alias: text(),
|
||||||
|
|
||||||
userId: userId()
|
userId: userId()
|
||||||
.notNull()
|
.notNull()
|
||||||
|
@ -144,9 +153,14 @@ export const projects = pgTable(
|
||||||
},
|
},
|
||||||
(table) => [
|
(table) => [
|
||||||
uniqueIndex('project_identifier_idx').on(table.identifier),
|
uniqueIndex('project_identifier_idx').on(table.identifier),
|
||||||
|
index('project_namespace_idx').on(table.namespace),
|
||||||
index('project_userId_idx').on(table.userId),
|
index('project_userId_idx').on(table.userId),
|
||||||
index('project_teamId_idx').on(table.teamId),
|
index('project_teamId_idx').on(table.teamId),
|
||||||
index('project_alias_idx').on(table.alias),
|
// index('project_alias_idx').on(table.alias),
|
||||||
|
index('project_private_idx').on(table.private),
|
||||||
|
index('project_lastPublishedDeploymentId_idx').on(
|
||||||
|
table.lastPublishedDeploymentId
|
||||||
|
),
|
||||||
index('project_createdAt_idx').on(table.createdAt),
|
index('project_createdAt_idx').on(table.createdAt),
|
||||||
index('project_updatedAt_idx').on(table.updatedAt),
|
index('project_updatedAt_idx').on(table.updatedAt),
|
||||||
index('project_deletedAt_idx').on(table.deletedAt)
|
index('project_deletedAt_idx').on(table.deletedAt)
|
||||||
|
@ -250,8 +264,8 @@ export const projectInsertSchema = createInsertSchema(projects, {
|
||||||
|
|
||||||
export const projectUpdateSchema = createUpdateSchema(projects)
|
export const projectUpdateSchema = createUpdateSchema(projects)
|
||||||
.pick({
|
.pick({
|
||||||
name: true,
|
name: true
|
||||||
alias: true
|
// alias: true
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { AgenticApiClient } from '@agentic/platform-api-client'
|
import { AgenticApiClient } from '@agentic/platform-api-client'
|
||||||
|
|
||||||
import { env } from '../src/env'
|
|
||||||
import { deployFixtures } from '../src/deploy-fixtures'
|
import { deployFixtures } from '../src/deploy-fixtures'
|
||||||
|
import { env } from '../src/env'
|
||||||
|
|
||||||
export const client = new AgenticApiClient({
|
export const client = new AgenticApiClient({
|
||||||
apiBaseUrl: env.AGENTIC_API_BASE_URL
|
apiBaseUrl: env.AGENTIC_API_BASE_URL
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useInfiniteQuery } from '@tanstack/react-query'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import useInfiniteScroll from 'react-infinite-scroll-hook'
|
||||||
|
|
||||||
|
import { useAgentic } from '@/components/agentic-provider'
|
||||||
|
import { LoadingIndicator } from '@/components/loading-indicator'
|
||||||
|
import { toastError } from '@/lib/notifications'
|
||||||
|
|
||||||
|
export function MarketplaceIndex() {
|
||||||
|
const ctx = useAgentic()
|
||||||
|
const limit = 10
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
isLoading,
|
||||||
|
isError,
|
||||||
|
hasNextPage,
|
||||||
|
fetchNextPage,
|
||||||
|
isFetchingNextPage
|
||||||
|
} = useInfiniteQuery({
|
||||||
|
queryKey: ['projects'],
|
||||||
|
queryFn: ({ pageParam = 0 }) =>
|
||||||
|
ctx!.api
|
||||||
|
.listPublicProjects({
|
||||||
|
populate: ['lastPublishedDeployment'],
|
||||||
|
offset: pageParam,
|
||||||
|
limit
|
||||||
|
})
|
||||||
|
.then(async (projects) => {
|
||||||
|
return {
|
||||||
|
projects,
|
||||||
|
offset: pageParam,
|
||||||
|
limit,
|
||||||
|
nextOffset:
|
||||||
|
projects.length >= limit ? pageParam + projects.length : undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err: any) => {
|
||||||
|
void toastError('Failed to fetch projects')
|
||||||
|
throw err
|
||||||
|
}),
|
||||||
|
getNextPageParam: (lastGroup) => lastGroup?.nextOffset,
|
||||||
|
enabled: !!ctx,
|
||||||
|
initialPageParam: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const [sentryRef] = useInfiniteScroll({
|
||||||
|
loading: isLoading || isFetchingNextPage,
|
||||||
|
hasNextPage,
|
||||||
|
onLoadMore: fetchNextPage,
|
||||||
|
disabled: !ctx || isError,
|
||||||
|
rootMargin: '0px 0px 200px 0px'
|
||||||
|
})
|
||||||
|
|
||||||
|
const projects = data ? data.pages.flatMap((p) => p.projects) : []
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<section>
|
||||||
|
<h1
|
||||||
|
className='text-center text-balance leading-snug md:leading-none
|
||||||
|
text-4xl font-extrabold'
|
||||||
|
>
|
||||||
|
Dashboard
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{!ctx || isLoading ? (
|
||||||
|
<LoadingIndicator />
|
||||||
|
) : (
|
||||||
|
<div className='mt-8'>
|
||||||
|
<h2 className='text-xl font-semibold mb-4'>Your Projects</h2>
|
||||||
|
|
||||||
|
{isError ? (
|
||||||
|
<p>Error fetching projects</p>
|
||||||
|
) : !projects.length ? (
|
||||||
|
<p>
|
||||||
|
No projects found. Create your first project to get started!
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<div className='grid gap-4'>
|
||||||
|
{projects.map((project) => (
|
||||||
|
<Link
|
||||||
|
key={project.id}
|
||||||
|
className='p-4 border rounded-lg hover:border-gray-400 transition-colors'
|
||||||
|
href={`/app/projects/${project.identifier}`}
|
||||||
|
>
|
||||||
|
<h3 className='font-medium'>{project.name}</h3>
|
||||||
|
|
||||||
|
<p className='text-sm text-gray-500'>
|
||||||
|
{project.identifier}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{project.lastPublishedDeployment && (
|
||||||
|
<p className='text-sm text-gray-500 mt-1'>
|
||||||
|
Last published:{' '}
|
||||||
|
{project.lastPublishedDeployment.version ||
|
||||||
|
project.lastPublishedDeployment.hash}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{hasNextPage && (
|
||||||
|
<div ref={sentryRef} className=''>
|
||||||
|
{isLoading || (isFetchingNextPage && <LoadingIndicator />)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { MarketplaceIndex } from './marketplace-index'
|
||||||
|
|
||||||
|
export default function MarketplaceIndexPage() {
|
||||||
|
return <MarketplaceIndex />
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useQuery } from '@tanstack/react-query'
|
||||||
|
|
||||||
|
import { useAgentic } from '@/components/agentic-provider'
|
||||||
|
import { LoadingIndicator } from '@/components/loading-indicator'
|
||||||
|
import { toastError } from '@/lib/notifications'
|
||||||
|
|
||||||
|
export function MarketplaceProjectIndex({
|
||||||
|
projectIdentifier
|
||||||
|
}: {
|
||||||
|
projectIdentifier: string
|
||||||
|
}) {
|
||||||
|
const ctx = useAgentic()
|
||||||
|
const {
|
||||||
|
data: project,
|
||||||
|
isLoading,
|
||||||
|
isError
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ['project', projectIdentifier],
|
||||||
|
queryFn: () =>
|
||||||
|
ctx!.api
|
||||||
|
.getPublicProjectByIdentifier({
|
||||||
|
projectIdentifier,
|
||||||
|
populate: ['lastPublishedDeployment']
|
||||||
|
})
|
||||||
|
.catch((err: any) => {
|
||||||
|
void toastError(`Failed to fetch project "${projectIdentifier}"`)
|
||||||
|
throw err
|
||||||
|
}),
|
||||||
|
enabled: !!ctx
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
{!ctx || isLoading ? (
|
||||||
|
<LoadingIndicator />
|
||||||
|
) : isError ? (
|
||||||
|
<p>Error fetching project</p>
|
||||||
|
) : !project ? (
|
||||||
|
<p>Project "{projectIdentifier}" not found</p>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<h1
|
||||||
|
className='text-center text-balance leading-snug md:leading-none
|
||||||
|
text-4xl font-extrabold'
|
||||||
|
>
|
||||||
|
Project {project.name}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div className='mt-8'>
|
||||||
|
<pre className='max-w-lg'>{JSON.stringify(project, null, 2)}</pre>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { parseProjectIdentifier } from '@agentic/platform-validators'
|
||||||
|
import { notFound } from 'next/navigation'
|
||||||
|
|
||||||
|
import { toastError } from '@/lib/notifications'
|
||||||
|
|
||||||
|
import { MarketplaceProjectIndex } from './marketplace-project-index'
|
||||||
|
|
||||||
|
export default async function MarketplaceProjectIndexPage({
|
||||||
|
params
|
||||||
|
}: {
|
||||||
|
params: Promise<{
|
||||||
|
namespace: string
|
||||||
|
'project-name': string
|
||||||
|
}>
|
||||||
|
}) {
|
||||||
|
const { namespace: rawNamespace, 'project-name': rawProjectName } =
|
||||||
|
await params
|
||||||
|
|
||||||
|
try {
|
||||||
|
const namespace = decodeURIComponent(rawNamespace)
|
||||||
|
const projectName = decodeURIComponent(rawProjectName)
|
||||||
|
|
||||||
|
const { projectIdentifier } = parseProjectIdentifier(
|
||||||
|
`${namespace}/${projectName}`,
|
||||||
|
{ strict: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
return <MarketplaceProjectIndex projectIdentifier={projectIdentifier} />
|
||||||
|
} catch (err: any) {
|
||||||
|
void toastError(err, { label: 'Invalid project identifier' })
|
||||||
|
|
||||||
|
return notFound()
|
||||||
|
}
|
||||||
|
}
|
|
@ -230,9 +230,10 @@ export class AgenticApiClient {
|
||||||
/** Gets the currently authenticated user. */
|
/** Gets the currently authenticated user. */
|
||||||
async getMe(): Promise<User> {
|
async getMe(): Promise<User> {
|
||||||
// const user = await this.verifyAuthAndRefreshIfNecessary()
|
// const user = await this.verifyAuthAndRefreshIfNecessary()
|
||||||
assert(this._authSession)
|
const userId = this._authSession?.user.id
|
||||||
|
assert(userId, 'This method requires authentication.')
|
||||||
|
|
||||||
return this.ky.get(`v1/users/${this._authSession.user.id}`).json()
|
return this.ky.get(`v1/users/${userId}`).json()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a user by ID. */
|
/** Gets a user by ID. */
|
||||||
|
@ -335,7 +336,65 @@ export class AgenticApiClient {
|
||||||
.json()
|
.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Lists projects the authenticated user has access to. */
|
/** Lists projects that have been published publicly to the marketplace. */
|
||||||
|
async listPublicProjects<
|
||||||
|
TPopulate extends NonNullable<
|
||||||
|
OperationParameters<'listPublicProjects'>['populate']
|
||||||
|
>[number]
|
||||||
|
>(
|
||||||
|
searchParams: OperationParameters<'listPublicProjects'> & {
|
||||||
|
populate?: TPopulate[]
|
||||||
|
} = {}
|
||||||
|
): Promise<Array<PopulateProject<TPopulate>>> {
|
||||||
|
return this.ky
|
||||||
|
.get('v1/projects', { searchParams: sanitizeSearchParams(searchParams) })
|
||||||
|
.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a public project by ID. The project must be publicly available on
|
||||||
|
* the marketplace.
|
||||||
|
*/
|
||||||
|
async getPublicProject<
|
||||||
|
TPopulate extends NonNullable<
|
||||||
|
OperationParameters<'getPublicProject'>['populate']
|
||||||
|
>[number]
|
||||||
|
>({
|
||||||
|
projectId,
|
||||||
|
...searchParams
|
||||||
|
}: OperationParameters<'getPublicProject'> & {
|
||||||
|
populate?: TPopulate[]
|
||||||
|
}): Promise<PopulateProject<TPopulate>> {
|
||||||
|
return this.ky
|
||||||
|
.get(`v1/projects/public/${projectId}`, {
|
||||||
|
searchParams: sanitizeSearchParams(searchParams)
|
||||||
|
})
|
||||||
|
.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a public project by its identifier. The project must be publicly
|
||||||
|
* available on the marketplace.
|
||||||
|
*/
|
||||||
|
async getPublicProjectByIdentifier<
|
||||||
|
TPopulate extends NonNullable<
|
||||||
|
OperationParameters<'getPublicProjectByIdentifier'>['populate']
|
||||||
|
>[number]
|
||||||
|
>(
|
||||||
|
searchParams: OperationParameters<'getPublicProjectByIdentifier'> & {
|
||||||
|
populate?: TPopulate[]
|
||||||
|
}
|
||||||
|
): Promise<PopulateProject<TPopulate>> {
|
||||||
|
return this.ky
|
||||||
|
.get('v1/projects/public/by-identifier', {
|
||||||
|
searchParams: sanitizeSearchParams(searchParams)
|
||||||
|
})
|
||||||
|
.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists projects the authenticated user has access to.
|
||||||
|
*/
|
||||||
async listProjects<
|
async listProjects<
|
||||||
TPopulate extends NonNullable<
|
TPopulate extends NonNullable<
|
||||||
OperationParameters<'listProjects'>['populate']
|
OperationParameters<'listProjects'>['populate']
|
||||||
|
@ -346,7 +405,9 @@ export class AgenticApiClient {
|
||||||
} = {}
|
} = {}
|
||||||
): Promise<Array<PopulateProject<TPopulate>>> {
|
): Promise<Array<PopulateProject<TPopulate>>> {
|
||||||
return this.ky
|
return this.ky
|
||||||
.get('v1/projects', { searchParams: sanitizeSearchParams(searchParams) })
|
.get(`v1/projects`, {
|
||||||
|
searchParams: sanitizeSearchParams(searchParams)
|
||||||
|
})
|
||||||
.json()
|
.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +419,9 @@ export class AgenticApiClient {
|
||||||
return this.ky.post('v1/projects', { json: project, searchParams }).json()
|
return this.ky.post('v1/projects', { json: project, searchParams }).json()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a project by ID. */
|
/**
|
||||||
|
* Gets a project by ID. Authenticated user must have access to the project.
|
||||||
|
*/
|
||||||
async getProject<
|
async getProject<
|
||||||
TPopulate extends NonNullable<
|
TPopulate extends NonNullable<
|
||||||
OperationParameters<'getProject'>['populate']
|
OperationParameters<'getProject'>['populate']
|
||||||
|
@ -376,7 +439,10 @@ export class AgenticApiClient {
|
||||||
.json()
|
.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a project by its public identifier. */
|
/**
|
||||||
|
* Gets a project by its identifier. Authenticated user must have access to
|
||||||
|
* the project.
|
||||||
|
*/
|
||||||
async getProjectByIdentifier<
|
async getProjectByIdentifier<
|
||||||
TPopulate extends NonNullable<
|
TPopulate extends NonNullable<
|
||||||
OperationParameters<'getProjectByIdentifier'>['populate']
|
OperationParameters<'getProjectByIdentifier'>['populate']
|
||||||
|
@ -393,7 +459,9 @@ export class AgenticApiClient {
|
||||||
.json()
|
.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Updates a project. */
|
/**
|
||||||
|
* Updates a project. Authenticated user must have access to the project.
|
||||||
|
*/
|
||||||
async updateProject(
|
async updateProject(
|
||||||
project: OperationBody<'updateProject'>,
|
project: OperationBody<'updateProject'>,
|
||||||
{ projectId, ...searchParams }: OperationParameters<'updateProject'>
|
{ projectId, ...searchParams }: OperationParameters<'updateProject'>
|
||||||
|
|
|
@ -89,6 +89,57 @@ export interface paths {
|
||||||
patch?: never;
|
patch?: never;
|
||||||
trace?: never;
|
trace?: never;
|
||||||
};
|
};
|
||||||
|
"/v1/projects/public": {
|
||||||
|
parameters: {
|
||||||
|
query?: never;
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
/** @description Lists projects that have been published publicly to the marketplace. */
|
||||||
|
get: operations["listPublicProjects"];
|
||||||
|
put?: never;
|
||||||
|
post?: never;
|
||||||
|
delete?: never;
|
||||||
|
options?: never;
|
||||||
|
head?: never;
|
||||||
|
patch?: never;
|
||||||
|
trace?: never;
|
||||||
|
};
|
||||||
|
"/v1/projects/public/by-identifier": {
|
||||||
|
parameters: {
|
||||||
|
query?: never;
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
/** @description Gets a public project by its public identifier (eg, "@username/project-name"). */
|
||||||
|
get: operations["getPublicProjectByIdentifier"];
|
||||||
|
put?: never;
|
||||||
|
post?: never;
|
||||||
|
delete?: never;
|
||||||
|
options?: never;
|
||||||
|
head?: never;
|
||||||
|
patch?: never;
|
||||||
|
trace?: never;
|
||||||
|
};
|
||||||
|
"/v1/projects/public/{projectId}": {
|
||||||
|
parameters: {
|
||||||
|
query?: never;
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
/** @description Gets a public project by ID. */
|
||||||
|
get: operations["getPublicProject"];
|
||||||
|
put?: never;
|
||||||
|
post?: never;
|
||||||
|
delete?: never;
|
||||||
|
options?: never;
|
||||||
|
head?: never;
|
||||||
|
patch?: never;
|
||||||
|
trace?: never;
|
||||||
|
};
|
||||||
"/v1/users/{userId}": {
|
"/v1/users/{userId}": {
|
||||||
parameters: {
|
parameters: {
|
||||||
query?: never;
|
query?: never;
|
||||||
|
@ -186,7 +237,7 @@ export interface paths {
|
||||||
path?: never;
|
path?: never;
|
||||||
cookie?: never;
|
cookie?: never;
|
||||||
};
|
};
|
||||||
/** @description Lists projects the authenticated user has access to. */
|
/** @description Lists projects owned by the authenticated user or team. */
|
||||||
get: operations["listProjects"];
|
get: operations["listProjects"];
|
||||||
put?: never;
|
put?: never;
|
||||||
/** @description Creates a new project. */
|
/** @description Creates a new project. */
|
||||||
|
@ -445,6 +496,39 @@ export interface components {
|
||||||
token: string;
|
token: string;
|
||||||
user: components["schemas"]["User"];
|
user: components["schemas"]["User"];
|
||||||
};
|
};
|
||||||
|
/** @description Public project identifier (e.g. "@namespace/project-name") */
|
||||||
|
ProjectIdentifier: string;
|
||||||
|
/** @description The frequency at which a subscription is billed. */
|
||||||
|
PricingInterval: "day" | "week" | "month" | "year";
|
||||||
|
/** @description A Project represents a single Agentic API product. A Project is comprised of a series of immutable Deployments, each of which contains pricing data, origin API config, OpenAPI or MCP specs, tool definitions, and various metadata.
|
||||||
|
*
|
||||||
|
* You can think of Agentic Projects as similar to Vercel projects. They both hold some common configuration and are comprised of a series of immutable Deployments.
|
||||||
|
*
|
||||||
|
* Internally, Projects manage all of the Stripe billing resources across Deployments (Stripe Products, Prices, and Meters for usage-based billing). */
|
||||||
|
Project: {
|
||||||
|
/** @description Project id (e.g. "proj_tz4a98xxat96iws9zmbrgj3a") */
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
deletedAt?: string;
|
||||||
|
identifier: components["schemas"]["ProjectIdentifier"];
|
||||||
|
namespace: string;
|
||||||
|
name: string;
|
||||||
|
private: boolean;
|
||||||
|
/** @description User id (e.g. "user_tz4a98xxat96iws9zmbrgj3a") */
|
||||||
|
userId: string;
|
||||||
|
/** @description Team id (e.g. "team_tz4a98xxat96iws9zmbrgj3a") */
|
||||||
|
teamId?: string;
|
||||||
|
/** @description Deployment id (e.g. "depl_tz4a98xxat96iws9zmbrgj3a") */
|
||||||
|
lastPublishedDeploymentId?: string;
|
||||||
|
/** @description Deployment id (e.g. "depl_tz4a98xxat96iws9zmbrgj3a") */
|
||||||
|
lastDeploymentId?: string;
|
||||||
|
lastPublishedDeploymentVersion?: string;
|
||||||
|
applicationFeePercent: number;
|
||||||
|
defaultPricingInterval: components["schemas"]["PricingInterval"];
|
||||||
|
/** @enum {string} */
|
||||||
|
pricingCurrency: "usd";
|
||||||
|
};
|
||||||
Team: {
|
Team: {
|
||||||
id: string;
|
id: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
|
@ -466,38 +550,6 @@ export interface components {
|
||||||
confirmed: boolean;
|
confirmed: boolean;
|
||||||
confirmedAt?: string;
|
confirmedAt?: string;
|
||||||
};
|
};
|
||||||
/** @description Public project identifier (e.g. "@namespace/project-name") */
|
|
||||||
ProjectIdentifier: string;
|
|
||||||
/** @description The frequency at which a subscription is billed. */
|
|
||||||
PricingInterval: "day" | "week" | "month" | "year";
|
|
||||||
/** @description A Project represents a single Agentic API product. A Project is comprised of a series of immutable Deployments, each of which contains pricing data, origin API config, OpenAPI or MCP specs, tool definitions, and various metadata.
|
|
||||||
*
|
|
||||||
* You can think of Agentic Projects as similar to Vercel projects. They both hold some common configuration and are comprised of a series of immutable Deployments.
|
|
||||||
*
|
|
||||||
* Internally, Projects manage all of the Stripe billing resources across Deployments (Stripe Products, Prices, and Meters for usage-based billing). */
|
|
||||||
Project: {
|
|
||||||
/** @description Project id (e.g. "proj_tz4a98xxat96iws9zmbrgj3a") */
|
|
||||||
id: string;
|
|
||||||
createdAt: string;
|
|
||||||
updatedAt: string;
|
|
||||||
deletedAt?: string;
|
|
||||||
identifier: components["schemas"]["ProjectIdentifier"];
|
|
||||||
name: string;
|
|
||||||
alias?: string;
|
|
||||||
/** @description User id (e.g. "user_tz4a98xxat96iws9zmbrgj3a") */
|
|
||||||
userId: string;
|
|
||||||
/** @description Team id (e.g. "team_tz4a98xxat96iws9zmbrgj3a") */
|
|
||||||
teamId?: string;
|
|
||||||
/** @description Deployment id (e.g. "depl_tz4a98xxat96iws9zmbrgj3a") */
|
|
||||||
lastPublishedDeploymentId?: string;
|
|
||||||
/** @description Deployment id (e.g. "depl_tz4a98xxat96iws9zmbrgj3a") */
|
|
||||||
lastDeploymentId?: string;
|
|
||||||
lastPublishedDeploymentVersion?: string;
|
|
||||||
applicationFeePercent: number;
|
|
||||||
defaultPricingInterval: components["schemas"]["PricingInterval"];
|
|
||||||
/** @enum {string} */
|
|
||||||
pricingCurrency: "usd";
|
|
||||||
};
|
|
||||||
/** @description A Consumer represents a user who has subscribed to a Project and is used
|
/** @description A Consumer represents a user who has subscribed to a Project and is used
|
||||||
* to track usage and billing.
|
* to track usage and billing.
|
||||||
*
|
*
|
||||||
|
@ -1065,6 +1117,92 @@ export interface operations {
|
||||||
404: components["responses"]["404"];
|
404: components["responses"]["404"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
listPublicProjects: {
|
||||||
|
parameters: {
|
||||||
|
query?: {
|
||||||
|
offset?: number | null;
|
||||||
|
limit?: number;
|
||||||
|
sort?: "asc" | "desc";
|
||||||
|
sortBy?: "createdAt" | "updatedAt";
|
||||||
|
populate?: ("user" | "team" | "lastPublishedDeployment" | "lastDeployment") | ("user" | "team" | "lastPublishedDeployment" | "lastDeployment")[];
|
||||||
|
};
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
requestBody?: never;
|
||||||
|
responses: {
|
||||||
|
/** @description A list of projects */
|
||||||
|
200: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown;
|
||||||
|
};
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["Project"][];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
400: components["responses"]["400"];
|
||||||
|
401: components["responses"]["401"];
|
||||||
|
403: components["responses"]["403"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
getPublicProjectByIdentifier: {
|
||||||
|
parameters: {
|
||||||
|
query: {
|
||||||
|
populate?: ("user" | "team" | "lastPublishedDeployment" | "lastDeployment") | ("user" | "team" | "lastPublishedDeployment" | "lastDeployment")[];
|
||||||
|
/** @description Public project identifier (e.g. "@namespace/project-name") */
|
||||||
|
projectIdentifier: components["schemas"]["ProjectIdentifier"];
|
||||||
|
};
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
requestBody?: never;
|
||||||
|
responses: {
|
||||||
|
/** @description A project */
|
||||||
|
200: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown;
|
||||||
|
};
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["Project"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
400: components["responses"]["400"];
|
||||||
|
401: components["responses"]["401"];
|
||||||
|
403: components["responses"]["403"];
|
||||||
|
404: components["responses"]["404"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
getPublicProject: {
|
||||||
|
parameters: {
|
||||||
|
query?: {
|
||||||
|
populate?: ("user" | "team" | "lastPublishedDeployment" | "lastDeployment") | ("user" | "team" | "lastPublishedDeployment" | "lastDeployment")[];
|
||||||
|
};
|
||||||
|
header?: never;
|
||||||
|
path: {
|
||||||
|
/** @description Project ID */
|
||||||
|
projectId: string;
|
||||||
|
};
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
requestBody?: never;
|
||||||
|
responses: {
|
||||||
|
/** @description A project */
|
||||||
|
200: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown;
|
||||||
|
};
|
||||||
|
content: {
|
||||||
|
"application/json": components["schemas"]["Project"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
400: components["responses"]["400"];
|
||||||
|
401: components["responses"]["401"];
|
||||||
|
403: components["responses"]["403"];
|
||||||
|
404: components["responses"]["404"];
|
||||||
|
};
|
||||||
|
};
|
||||||
getUser: {
|
getUser: {
|
||||||
parameters: {
|
parameters: {
|
||||||
query?: never;
|
query?: never;
|
||||||
|
@ -1505,7 +1643,6 @@ export interface operations {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
name?: string;
|
name?: string;
|
||||||
alias?: string;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
- hosted docs
|
- hosted docs
|
||||||
- merge with current agentic repo
|
- merge with current agentic repo
|
||||||
- publish packages to npm
|
- publish packages to npm
|
||||||
|
- api
|
||||||
|
- deploy to prod
|
||||||
- database
|
- database
|
||||||
- consider using [neon serverless driver](https://orm.drizzle.team/docs/connect-neon) for production
|
- consider using [neon serverless driver](https://orm.drizzle.team/docs/connect-neon) for production
|
||||||
- can this also be used locally?
|
- can this also be used locally?
|
||||||
|
|
Ładowanie…
Reference in New Issue