Turborepo monorepo with @forte/shared and @forte/backend workspaces. Docker Compose dev env with PostgreSQL 16 + Valkey 8. Fastify server with Pino JSON logging, request ID tracing, and health endpoint. Drizzle ORM with company + location tables. Includes: - Root config (turbo, tsconfig, eslint, prettier) - @forte/shared: types, schemas, currency/date utils - @forte/backend: Fastify entry, plugins (database, redis, cors, error-handler, dev-auth), health route, Drizzle schema + migration - Dev auth bypass via X-Dev-Company/Location/User headers - Vitest integration test with clean DB per test (forte_test) - Seed script for dev company + location
38 lines
1.5 KiB
TypeScript
38 lines
1.5 KiB
TypeScript
import { pgTable, uuid, varchar, text, jsonb, timestamp, boolean } from 'drizzle-orm/pg-core'
|
|
|
|
export const companies = pgTable('company', {
|
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
name: varchar('name', { length: 255 }).notNull(),
|
|
phone: varchar('phone', { length: 50 }),
|
|
email: varchar('email', { length: 255 }),
|
|
timezone: varchar('timezone', { length: 100 }).notNull().default('America/Chicago'),
|
|
notes: text('notes'),
|
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
})
|
|
|
|
export const locations = pgTable('location', {
|
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
companyId: uuid('company_id')
|
|
.notNull()
|
|
.references(() => companies.id),
|
|
name: varchar('name', { length: 255 }).notNull(),
|
|
address: jsonb('address').$type<{
|
|
street?: string
|
|
city?: string
|
|
state?: string
|
|
zip?: string
|
|
}>(),
|
|
phone: varchar('phone', { length: 50 }),
|
|
email: varchar('email', { length: 255 }),
|
|
timezone: varchar('timezone', { length: 100 }),
|
|
isActive: boolean('is_active').notNull().default(true),
|
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
})
|
|
|
|
export type Company = typeof companies.$inferSelect
|
|
export type CompanyInsert = typeof companies.$inferInsert
|
|
export type Location = typeof locations.$inferSelect
|
|
export type LocationInsert = typeof locations.$inferInsert
|