kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
pull/715/head
rodzic
67ffdd89f6
commit
80f6655ada
|
@ -47,6 +47,7 @@
|
||||||
"@paralleldrive/cuid2": "^2.2.2",
|
"@paralleldrive/cuid2": "^2.2.2",
|
||||||
"@sentry/node": "^9.14.0",
|
"@sentry/node": "^9.14.0",
|
||||||
"@workos-inc/node": "^7.47.0",
|
"@workos-inc/node": "^7.47.0",
|
||||||
|
"bcryptjs": "^3.0.2",
|
||||||
"eventid": "^2.0.1",
|
"eventid": "^2.0.1",
|
||||||
"exit-hook": "catalog:",
|
"exit-hook": "catalog:",
|
||||||
"hono": "^4.7.7",
|
"hono": "^4.7.7",
|
||||||
|
|
|
@ -107,12 +107,18 @@ export const consumersRelations = relations(consumers, ({ one }) => ({
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const stripeValidSubscriptionStatuses = new Set([
|
const stripeValidSubscriptionStatuses = new Set([
|
||||||
'trialing',
|
|
||||||
'active',
|
'active',
|
||||||
|
'trialing',
|
||||||
'incomplete',
|
'incomplete',
|
||||||
'past_due'
|
'past_due'
|
||||||
])
|
])
|
||||||
|
|
||||||
|
export const consumerSelectSchema = createSelectSchema(consumers)
|
||||||
|
.openapi('Consumer')
|
||||||
|
.omit({
|
||||||
|
_stripeCustomerId: true
|
||||||
|
})
|
||||||
|
|
||||||
export const consumerInsertSchema = createInsertSchema(consumers).pick({
|
export const consumerInsertSchema = createInsertSchema(consumers).pick({
|
||||||
token: true,
|
token: true,
|
||||||
plan: true,
|
plan: true,
|
||||||
|
@ -124,16 +130,14 @@ export const consumerInsertSchema = createInsertSchema(consumers).pick({
|
||||||
deploymentId: true
|
deploymentId: true
|
||||||
})
|
})
|
||||||
|
|
||||||
export const consumerSelectSchema =
|
|
||||||
createSelectSchema(consumers).openapi('Consumer')
|
|
||||||
|
|
||||||
export const consumerUpdateSchema = createUpdateSchema(consumers).refine(
|
export const consumerUpdateSchema = createUpdateSchema(consumers).refine(
|
||||||
(data) => {
|
(consumer) => {
|
||||||
return {
|
return {
|
||||||
...data,
|
...consumer,
|
||||||
enabled:
|
enabled:
|
||||||
data.plan === 'free' ||
|
consumer.plan === 'free' ||
|
||||||
(data.status && stripeValidSubscriptionStatuses.has(data.status))
|
(consumer.status &&
|
||||||
|
stripeValidSubscriptionStatuses.has(consumer.status))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -105,7 +105,17 @@ export const deploymentsRelations = relations(deployments, ({ one }) => ({
|
||||||
// TODO: virtual authProviders?
|
// TODO: virtual authProviders?
|
||||||
// TODO: virtual openapi spec? (hide openapi.servers)
|
// TODO: virtual openapi spec? (hide openapi.servers)
|
||||||
|
|
||||||
// TODO: narrow
|
export const deploymentSelectSchema = createSelectSchema(deployments, {
|
||||||
|
// build: z.object({}),
|
||||||
|
// env: z.object({}),
|
||||||
|
pricingPlans: z.array(pricingPlanSchema),
|
||||||
|
coupons: z.array(couponSchema)
|
||||||
|
})
|
||||||
|
.omit({
|
||||||
|
_url: true
|
||||||
|
})
|
||||||
|
.openapi('Deployment')
|
||||||
|
|
||||||
export const deploymentInsertSchema = createInsertSchema(deployments, {
|
export const deploymentInsertSchema = createInsertSchema(deployments, {
|
||||||
id: (schema) =>
|
id: (schema) =>
|
||||||
schema.refine((id) => validators.project(id), {
|
schema.refine((id) => validators.project(id), {
|
||||||
|
@ -123,18 +133,7 @@ export const deploymentInsertSchema = createInsertSchema(deployments, {
|
||||||
// env: z.object({}),
|
// env: z.object({}),
|
||||||
pricingPlans: z.array(pricingPlanSchema),
|
pricingPlans: z.array(pricingPlanSchema),
|
||||||
coupons: z.array(couponSchema).optional()
|
coupons: z.array(couponSchema).optional()
|
||||||
})
|
}).omit({ id: true, createdAt: true, updatedAt: true })
|
||||||
|
|
||||||
export const deploymentSelectSchema = createSelectSchema(deployments, {
|
|
||||||
// build: z.object({}),
|
|
||||||
// env: z.object({}),
|
|
||||||
pricingPlans: z.array(pricingPlanSchema),
|
|
||||||
coupons: z.array(couponSchema)
|
|
||||||
})
|
|
||||||
.omit({
|
|
||||||
_url: true
|
|
||||||
})
|
|
||||||
.openapi('Deployment')
|
|
||||||
|
|
||||||
export const deploymentUpdateSchema = createUpdateSchema(deployments).pick({
|
export const deploymentUpdateSchema = createUpdateSchema(deployments).pick({
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export * from './consumer'
|
export * from './consumer'
|
||||||
export * from './deployment'
|
export * from './deployment'
|
||||||
|
export * from './log-entry'
|
||||||
export * from './project'
|
export * from './project'
|
||||||
export * from './team'
|
export * from './team'
|
||||||
export * from './team-member'
|
export * from './team-member'
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
import { relations } from '@fisch0920/drizzle-orm'
|
||||||
|
import { index, pgTable, text } from '@fisch0920/drizzle-orm/pg-core'
|
||||||
|
|
||||||
|
import { consumers } from './consumer'
|
||||||
|
import { deployments } from './deployment'
|
||||||
|
import { projects } from './project'
|
||||||
|
import { users } from './user'
|
||||||
|
import {
|
||||||
|
createInsertSchema,
|
||||||
|
createSelectSchema,
|
||||||
|
cuid,
|
||||||
|
deploymentId,
|
||||||
|
id,
|
||||||
|
projectId,
|
||||||
|
stripeId,
|
||||||
|
timestamps
|
||||||
|
} from './utils'
|
||||||
|
|
||||||
|
export const logEntries = pgTable(
|
||||||
|
'log_entries',
|
||||||
|
{
|
||||||
|
id,
|
||||||
|
...timestamps,
|
||||||
|
|
||||||
|
type: text().notNull(),
|
||||||
|
level: text().notNull().default('info'), // TODO: enum
|
||||||
|
|
||||||
|
// relations
|
||||||
|
userId: cuid(),
|
||||||
|
projectId: projectId(),
|
||||||
|
deploymentId: deploymentId(),
|
||||||
|
consumerId: cuid(),
|
||||||
|
|
||||||
|
// (optional) misc context info
|
||||||
|
service: text(),
|
||||||
|
hostname: text(),
|
||||||
|
provider: text(),
|
||||||
|
ip: text(),
|
||||||
|
plan: text(),
|
||||||
|
subtype: text(),
|
||||||
|
|
||||||
|
// (optional) denormalized info
|
||||||
|
username: text(),
|
||||||
|
email: text(),
|
||||||
|
token: text(),
|
||||||
|
|
||||||
|
// (optional) denormalized stripe info
|
||||||
|
stripeCustomer: stripeId(),
|
||||||
|
stripeSubscription: stripeId()
|
||||||
|
},
|
||||||
|
(table) => [
|
||||||
|
index('log_entry_type_idx').on(table.type),
|
||||||
|
index('log_entry_userId_idx').on(table.userId),
|
||||||
|
index('log_entry_projectId_idx').on(table.projectId),
|
||||||
|
index('log_entry_deploymentId_idx').on(table.deploymentId),
|
||||||
|
index('log_entry_consumerId_idx').on(table.consumerId),
|
||||||
|
index('log_entry_createdAt_idx').on(table.createdAt),
|
||||||
|
index('log_entry_updatedAt_idx').on(table.updatedAt)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
export const logEntriesRelations = relations(logEntries, ({ one }) => ({
|
||||||
|
user: one(users, {
|
||||||
|
fields: [logEntries.userId],
|
||||||
|
references: [users.id]
|
||||||
|
}),
|
||||||
|
project: one(projects, {
|
||||||
|
fields: [logEntries.projectId],
|
||||||
|
references: [projects.id]
|
||||||
|
}),
|
||||||
|
deployment: one(deployments, {
|
||||||
|
fields: [logEntries.deploymentId],
|
||||||
|
references: [deployments.id]
|
||||||
|
}),
|
||||||
|
consumer: one(consumers, {
|
||||||
|
fields: [logEntries.consumerId],
|
||||||
|
references: [consumers.id]
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
|
||||||
|
export const logEntrySelectSchema =
|
||||||
|
createSelectSchema(logEntries).openapi('LogEntry')
|
||||||
|
|
||||||
|
export const logEntryInsertSchema = createInsertSchema(logEntries).omit({
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
updatedAt: true
|
||||||
|
})
|
|
@ -134,29 +134,6 @@ export const projectsRelations = relations(projects, ({ one, many }) => ({
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
|
|
||||||
export const projectInsertSchema = createInsertSchema(projects, {
|
|
||||||
id: (schema) =>
|
|
||||||
schema.refine((id) => validators.project(id), {
|
|
||||||
message: 'Invalid project id'
|
|
||||||
}),
|
|
||||||
|
|
||||||
name: (schema) =>
|
|
||||||
schema.refine((name) => validators.projectName(name), {
|
|
||||||
message: 'Invalid project name'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.pick({
|
|
||||||
id: true,
|
|
||||||
name: true,
|
|
||||||
userId: true
|
|
||||||
})
|
|
||||||
.refine((data) => {
|
|
||||||
return {
|
|
||||||
...data,
|
|
||||||
_providerToken: getProviderToken(data)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export const projectSelectSchema = createSelectSchema(projects, {
|
export const projectSelectSchema = createSelectSchema(projects, {
|
||||||
stripeMetricProductIds: z.record(z.string(), z.string()).optional()
|
stripeMetricProductIds: z.record(z.string(), z.string()).optional()
|
||||||
// _webhooks: z.array(webhookSchema),
|
// _webhooks: z.array(webhookSchema),
|
||||||
|
@ -182,6 +159,29 @@ export const projectSelectSchema = createSelectSchema(projects, {
|
||||||
})
|
})
|
||||||
.openapi('Project')
|
.openapi('Project')
|
||||||
|
|
||||||
|
export const projectInsertSchema = createInsertSchema(projects, {
|
||||||
|
id: (schema) =>
|
||||||
|
schema.refine((id) => validators.project(id), {
|
||||||
|
message: 'Invalid project id'
|
||||||
|
}),
|
||||||
|
|
||||||
|
name: (schema) =>
|
||||||
|
schema.refine((name) => validators.projectName(name), {
|
||||||
|
message: 'Invalid project name'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.pick({
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
userId: true
|
||||||
|
})
|
||||||
|
.refine((data) => {
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
_providerToken: getProviderToken(data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// TODO: narrow update schema
|
// TODO: narrow update schema
|
||||||
export const projectUpdateSchema = createUpdateSchema(projects)
|
export const projectUpdateSchema = createUpdateSchema(projects)
|
||||||
|
|
||||||
|
|
|
@ -59,14 +59,14 @@ export const teamMembersRelations = relations(teamMembers, ({ one }) => ({
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
export const teamMemberSelectSchema =
|
||||||
|
createSelectSchema(teamMembers).openapi('TeamMember')
|
||||||
|
|
||||||
export const teamMemberInsertSchema = createInsertSchema(teamMembers).pick({
|
export const teamMemberInsertSchema = createInsertSchema(teamMembers).pick({
|
||||||
userId: true,
|
userId: true,
|
||||||
role: true
|
role: true
|
||||||
})
|
})
|
||||||
|
|
||||||
export const teamMemberSelectSchema =
|
|
||||||
createSelectSchema(teamMembers).openapi('TeamMember')
|
|
||||||
|
|
||||||
export const teamMemberUpdateSchema = createUpdateSchema(teamMembers).pick({
|
export const teamMemberUpdateSchema = createUpdateSchema(teamMembers).pick({
|
||||||
role: true
|
role: true
|
||||||
})
|
})
|
||||||
|
|
|
@ -45,6 +45,8 @@ export const teamsRelations = relations(teams, ({ one, many }) => ({
|
||||||
members: many(teamMembers)
|
members: many(teamMembers)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
export const teamSelectSchema = createSelectSchema(teams).openapi('Team')
|
||||||
|
|
||||||
export const teamInsertSchema = createInsertSchema(teams, {
|
export const teamInsertSchema = createInsertSchema(teams, {
|
||||||
slug: (schema) =>
|
slug: (schema) =>
|
||||||
schema.refine((slug) => validators.team(slug), {
|
schema.refine((slug) => validators.team(slug), {
|
||||||
|
@ -52,12 +54,7 @@ export const teamInsertSchema = createInsertSchema(teams, {
|
||||||
})
|
})
|
||||||
}).omit({ id: true, createdAt: true, updatedAt: true, ownerId: true })
|
}).omit({ id: true, createdAt: true, updatedAt: true, ownerId: true })
|
||||||
|
|
||||||
export const teamSelectSchema = createSelectSchema(teams).openapi('Team')
|
export const teamUpdateSchema = createUpdateSchema(teams).pick({
|
||||||
|
name: true,
|
||||||
export const teamUpdateSchema = createUpdateSchema(teams).omit({
|
ownerId: true
|
||||||
id: true,
|
|
||||||
createdAt: true,
|
|
||||||
updatedAt: true,
|
|
||||||
ownerId: true,
|
|
||||||
slug: true
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
text,
|
text,
|
||||||
uniqueIndex
|
uniqueIndex
|
||||||
} from '@fisch0920/drizzle-orm/pg-core'
|
} from '@fisch0920/drizzle-orm/pg-core'
|
||||||
|
import { hashSync } from 'bcryptjs'
|
||||||
|
|
||||||
import { sha256 } from '@/lib/utils'
|
import { sha256 } from '@/lib/utils'
|
||||||
|
|
||||||
|
@ -68,6 +69,15 @@ export const usersRelations = relations(users, ({ many }) => ({
|
||||||
teamsOwned: many(teams)
|
teamsOwned: many(teams)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
export const userSelectSchema = createSelectSchema(users).openapi('User')
|
||||||
|
|
||||||
|
function userRefinementHook(user: Partial<typeof users.$inferInsert>) {
|
||||||
|
return {
|
||||||
|
...user,
|
||||||
|
password: user.password ? hashSync(user.password) : undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const userInsertSchema = createInsertSchema(users, {
|
export const userInsertSchema = createInsertSchema(users, {
|
||||||
username: (schema) =>
|
username: (schema) =>
|
||||||
schema.refine((username) => validators.username(username), {
|
schema.refine((username) => validators.username(username), {
|
||||||
|
@ -77,22 +87,23 @@ export const userInsertSchema = createInsertSchema(users, {
|
||||||
email: (schema) => schema.email().optional(),
|
email: (schema) => schema.email().optional(),
|
||||||
|
|
||||||
providers: authProvidersSchema.optional()
|
providers: authProvidersSchema.optional()
|
||||||
}).pick({
|
|
||||||
username: true,
|
|
||||||
email: true,
|
|
||||||
password: true,
|
|
||||||
firstName: true,
|
|
||||||
lastName: true,
|
|
||||||
image: true
|
|
||||||
})
|
})
|
||||||
|
.pick({
|
||||||
|
username: true,
|
||||||
|
email: true,
|
||||||
|
password: true,
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
image: true
|
||||||
|
})
|
||||||
|
.refine(userRefinementHook)
|
||||||
|
|
||||||
export const userSelectSchema = createSelectSchema(users, {
|
export const userUpdateSchema = createUpdateSchema(users)
|
||||||
providers: authProvidersSchema
|
.pick({
|
||||||
}).openapi('User')
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
export const userUpdateSchema = createUpdateSchema(users).pick({
|
image: true,
|
||||||
firstName: true,
|
password: true,
|
||||||
lastName: true,
|
isStripeConnectEnabledByDefault: true
|
||||||
image: true,
|
})
|
||||||
isStripeConnectEnabledByDefault: true
|
.refine(userRefinementHook)
|
||||||
})
|
|
||||||
|
|
|
@ -50,13 +50,13 @@ export function deploymentId<U extends string, T extends Readonly<[U, ...U[]]>>(
|
||||||
|
|
||||||
export function username<U extends string, T extends Readonly<[U, ...U[]]>>(
|
export function username<U extends string, T extends Readonly<[U, ...U[]]>>(
|
||||||
config?: PgVarcharConfig<T | Writable<T>, never>
|
config?: PgVarcharConfig<T | Writable<T>, never>
|
||||||
): PgVarcharBuilderInitial<'', Writable<T>, 64> {
|
): PgVarcharBuilderInitial<'', Writable<T>, typeof usernameAndTeamSlugLength> {
|
||||||
return varchar({ length: usernameAndTeamSlugLength, ...config })
|
return varchar({ length: usernameAndTeamSlugLength, ...config })
|
||||||
}
|
}
|
||||||
|
|
||||||
export function teamSlug<U extends string, T extends Readonly<[U, ...U[]]>>(
|
export function teamSlug<U extends string, T extends Readonly<[U, ...U[]]>>(
|
||||||
config?: PgVarcharConfig<T | Writable<T>, never>
|
config?: PgVarcharConfig<T | Writable<T>, never>
|
||||||
): PgVarcharBuilderInitial<'', Writable<T>, 64> {
|
): PgVarcharBuilderInitial<'', Writable<T>, typeof usernameAndTeamSlugLength> {
|
||||||
return varchar({ length: usernameAndTeamSlugLength, ...config })
|
return varchar({ length: usernameAndTeamSlugLength, ...config })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/transitive-bullshit/agentic-platform.git"
|
"url": "git+https://github.com/transitive-bullshit/agentic-platform.git"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.9.0",
|
"packageManager": "pnpm@10.10.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
|
|
|
@ -158,6 +158,9 @@ importers:
|
||||||
'@workos-inc/node':
|
'@workos-inc/node':
|
||||||
specifier: ^7.47.0
|
specifier: ^7.47.0
|
||||||
version: 7.48.0
|
version: 7.48.0
|
||||||
|
bcryptjs:
|
||||||
|
specifier: ^3.0.2
|
||||||
|
version: 3.0.2
|
||||||
eventid:
|
eventid:
|
||||||
specifier: ^2.0.1
|
specifier: ^2.0.1
|
||||||
version: 2.0.1
|
version: 2.0.1
|
||||||
|
@ -1504,6 +1507,10 @@ packages:
|
||||||
base64-js@1.5.1:
|
base64-js@1.5.1:
|
||||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
|
||||||
|
bcryptjs@3.0.2:
|
||||||
|
resolution: {integrity: sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
bignumber.js@9.3.0:
|
bignumber.js@9.3.0:
|
||||||
resolution: {integrity: sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==}
|
resolution: {integrity: sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==}
|
||||||
|
|
||||||
|
@ -4899,6 +4906,8 @@ snapshots:
|
||||||
|
|
||||||
base64-js@1.5.1: {}
|
base64-js@1.5.1: {}
|
||||||
|
|
||||||
|
bcryptjs@3.0.2: {}
|
||||||
|
|
||||||
bignumber.js@9.3.0: {}
|
bignumber.js@9.3.0: {}
|
||||||
|
|
||||||
brace-expansion@1.1.11:
|
brace-expansion@1.1.11:
|
||||||
|
|
Ładowanie…
Reference in New Issue