pull/715/head
Travis Fischer 2025-04-30 08:41:16 +07:00
rodzic 67ffdd89f6
commit 80f6655ada
12 zmienionych plików z 185 dodań i 75 usunięć

Wyświetl plik

@ -47,6 +47,7 @@
"@paralleldrive/cuid2": "^2.2.2",
"@sentry/node": "^9.14.0",
"@workos-inc/node": "^7.47.0",
"bcryptjs": "^3.0.2",
"eventid": "^2.0.1",
"exit-hook": "catalog:",
"hono": "^4.7.7",

Wyświetl plik

@ -107,12 +107,18 @@ export const consumersRelations = relations(consumers, ({ one }) => ({
}))
const stripeValidSubscriptionStatuses = new Set([
'trialing',
'active',
'trialing',
'incomplete',
'past_due'
])
export const consumerSelectSchema = createSelectSchema(consumers)
.openapi('Consumer')
.omit({
_stripeCustomerId: true
})
export const consumerInsertSchema = createInsertSchema(consumers).pick({
token: true,
plan: true,
@ -124,16 +130,14 @@ export const consumerInsertSchema = createInsertSchema(consumers).pick({
deploymentId: true
})
export const consumerSelectSchema =
createSelectSchema(consumers).openapi('Consumer')
export const consumerUpdateSchema = createUpdateSchema(consumers).refine(
(data) => {
(consumer) => {
return {
...data,
...consumer,
enabled:
data.plan === 'free' ||
(data.status && stripeValidSubscriptionStatuses.has(data.status))
consumer.plan === 'free' ||
(consumer.status &&
stripeValidSubscriptionStatuses.has(consumer.status))
}
}
)

Wyświetl plik

@ -105,7 +105,17 @@ export const deploymentsRelations = relations(deployments, ({ one }) => ({
// TODO: virtual authProviders?
// 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, {
id: (schema) =>
schema.refine((id) => validators.project(id), {
@ -123,18 +133,7 @@ export const deploymentInsertSchema = createInsertSchema(deployments, {
// env: z.object({}),
pricingPlans: z.array(pricingPlanSchema),
coupons: z.array(couponSchema).optional()
})
export const deploymentSelectSchema = createSelectSchema(deployments, {
// build: z.object({}),
// env: z.object({}),
pricingPlans: z.array(pricingPlanSchema),
coupons: z.array(couponSchema)
})
.omit({
_url: true
})
.openapi('Deployment')
}).omit({ id: true, createdAt: true, updatedAt: true })
export const deploymentUpdateSchema = createUpdateSchema(deployments).pick({
enabled: true,

Wyświetl plik

@ -1,5 +1,6 @@
export * from './consumer'
export * from './deployment'
export * from './log-entry'
export * from './project'
export * from './team'
export * from './team-member'

Wyświetl plik

@ -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
})

Wyświetl plik

@ -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, {
stripeMetricProductIds: z.record(z.string(), z.string()).optional()
// _webhooks: z.array(webhookSchema),
@ -182,6 +159,29 @@ export const projectSelectSchema = createSelectSchema(projects, {
})
.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
export const projectUpdateSchema = createUpdateSchema(projects)

Wyświetl plik

@ -59,14 +59,14 @@ export const teamMembersRelations = relations(teamMembers, ({ one }) => ({
})
}))
export const teamMemberSelectSchema =
createSelectSchema(teamMembers).openapi('TeamMember')
export const teamMemberInsertSchema = createInsertSchema(teamMembers).pick({
userId: true,
role: true
})
export const teamMemberSelectSchema =
createSelectSchema(teamMembers).openapi('TeamMember')
export const teamMemberUpdateSchema = createUpdateSchema(teamMembers).pick({
role: true
})

Wyświetl plik

@ -45,6 +45,8 @@ export const teamsRelations = relations(teams, ({ one, many }) => ({
members: many(teamMembers)
}))
export const teamSelectSchema = createSelectSchema(teams).openapi('Team')
export const teamInsertSchema = createInsertSchema(teams, {
slug: (schema) =>
schema.refine((slug) => validators.team(slug), {
@ -52,12 +54,7 @@ export const teamInsertSchema = createInsertSchema(teams, {
})
}).omit({ id: true, createdAt: true, updatedAt: true, ownerId: true })
export const teamSelectSchema = createSelectSchema(teams).openapi('Team')
export const teamUpdateSchema = createUpdateSchema(teams).omit({
id: true,
createdAt: true,
updatedAt: true,
ownerId: true,
slug: true
export const teamUpdateSchema = createUpdateSchema(teams).pick({
name: true,
ownerId: true
})

Wyświetl plik

@ -8,6 +8,7 @@ import {
text,
uniqueIndex
} from '@fisch0920/drizzle-orm/pg-core'
import { hashSync } from 'bcryptjs'
import { sha256 } from '@/lib/utils'
@ -68,6 +69,15 @@ export const usersRelations = relations(users, ({ many }) => ({
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, {
username: (schema) =>
schema.refine((username) => validators.username(username), {
@ -77,22 +87,23 @@ export const userInsertSchema = createInsertSchema(users, {
email: (schema) => schema.email().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, {
providers: authProvidersSchema
}).openapi('User')
export const userUpdateSchema = createUpdateSchema(users).pick({
firstName: true,
lastName: true,
image: true,
isStripeConnectEnabledByDefault: true
})
export const userUpdateSchema = createUpdateSchema(users)
.pick({
firstName: true,
lastName: true,
image: true,
password: true,
isStripeConnectEnabledByDefault: true
})
.refine(userRefinementHook)

Wyświetl plik

@ -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[]]>>(
config?: PgVarcharConfig<T | Writable<T>, never>
): PgVarcharBuilderInitial<'', Writable<T>, 64> {
): PgVarcharBuilderInitial<'', Writable<T>, typeof usernameAndTeamSlugLength> {
return varchar({ length: usernameAndTeamSlugLength, ...config })
}
export function teamSlug<U extends string, T extends Readonly<[U, ...U[]]>>(
config?: PgVarcharConfig<T | Writable<T>, never>
): PgVarcharBuilderInitial<'', Writable<T>, 64> {
): PgVarcharBuilderInitial<'', Writable<T>, typeof usernameAndTeamSlugLength> {
return varchar({ length: usernameAndTeamSlugLength, ...config })
}

Wyświetl plik

@ -7,7 +7,7 @@
"type": "git",
"url": "git+https://github.com/transitive-bullshit/agentic-platform.git"
},
"packageManager": "pnpm@10.9.0",
"packageManager": "pnpm@10.10.0",
"engines": {
"node": ">=18"
},

Wyświetl plik

@ -158,6 +158,9 @@ importers:
'@workos-inc/node':
specifier: ^7.47.0
version: 7.48.0
bcryptjs:
specifier: ^3.0.2
version: 3.0.2
eventid:
specifier: ^2.0.1
version: 2.0.1
@ -1504,6 +1507,10 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
bcryptjs@3.0.2:
resolution: {integrity: sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==}
hasBin: true
bignumber.js@9.3.0:
resolution: {integrity: sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==}
@ -4899,6 +4906,8 @@ snapshots:
base64-js@1.5.1: {}
bcryptjs@3.0.2: {}
bignumber.js@9.3.0: {}
brace-expansion@1.1.11: