Remove foreign key handling from table quickstart

- Remove isForeign and references fields from Zod schema
- Remove relationships from TableSchema
- Update system prompt to not generate foreign key constraints
- Remove TableRelationship type and relationships from TableSuggestion
- Clean up all FK handling in conversion logic
- Simplify getColumnDescription to only handle primary keys
This commit is contained in:
Sean Oliver committed 2025-10-14 10:22:42 -07:00
1 parent 8ab841e6c0
commit c10c075ca4
3 files changed
+3 -67

No files matched your search

@@ -26,14 +26,6 @@ export type TableField = {
default?: string // Must be string for table editor compatibility
description?: string
isPrimary?: boolean
isForeign?: boolean
references?: string
}
export type TableRelationship = {
from: string
to: string
type: 'one-to-one' | 'one-to-many' | 'many-to-many' | 'many-to-one'
}
export enum TableSource {
@@ -47,19 +39,11 @@ export enum QuickstartVariant {
TEMPLATES = 'templates',
}
export enum ViewMode {
INITIAL = 'initial',
AI_INPUT = 'ai-input',
AI_RESULTS = 'ai-results',
CATEGORY_SELECTED = 'category-selected',
}
export type TableSuggestion = {
tableName: string
fields: TableField[]
rationale?: string
source: TableSource
relationships?: TableRelationship[]
}
export type AIGeneratedSchema = {
@@ -70,13 +54,10 @@ export type AIGeneratedSchema = {
name: string
type: string
isPrimary?: boolean
isForeign?: boolean
references?: string
isNullable?: boolean
defaultValue?: string
isUnique?: boolean
}>
relationships?: TableRelationship[]
}>
summary: string
}
@@ -3,7 +3,7 @@ import { BASE_PATH } from 'lib/constants'
import { useCallback, useEffect, useRef, useState } from 'react'
import { toast } from 'sonner'
import { LIMITS } from './constants'
import type { AIGeneratedSchema, PostgresType, TableRelationship, TableSuggestion } from './types'
import type { AIGeneratedSchema, PostgresType, TableSuggestion } from './types'
import { TableSource } from './types'
type PartialColumn = Partial<AIGeneratedSchema['tables'][number]['columns'][number]>
@@ -22,9 +22,8 @@ const isIdColumn = (name: string) => name === 'id'
const isPrimaryColumn = (column: { isPrimary?: boolean | null; name: string }) =>
column.isPrimary || isIdColumn(column.name)
const getColumnDescription = (column: { isPrimary?: boolean | null; name: string; isForeign?: boolean | null; references?: any }) => {
const getColumnDescription = (column: { isPrimary?: boolean | null; name: string }) => {
if (isPrimaryColumn(column)) return 'Primary key'
if (column.isForeign && column.references) return `References ${column.references}`
return undefined
}
@@ -66,12 +65,9 @@ const convertAISchemaToTableSuggestions = (schema: AIGeneratedSchema): TableSugg
default: column.defaultValue ?? undefined,
description: getColumnDescription(column),
isPrimary: isPrimaryColumn(column) || undefined,
isForeign: column.isForeign ?? undefined,
references: column.references ?? undefined,
})),
rationale: table.description,
source: TableSource.AI,
relationships: table.relationships ?? undefined,
}))
}
@@ -107,8 +103,6 @@ const convertPartialSchemaToTableSuggestions = (schema: PartialSchema): TableSug
default: column.defaultValue ?? undefined,
description: getColumnDescription({ ...column, name: columnName }),
isPrimary: isPrimaryColumn({ ...column, name: columnName }) || undefined,
isForeign: column.isForeign ?? undefined,
references: column.references ?? undefined,
}
})
.filter(isNotNull)
@@ -117,34 +111,11 @@ const convertPartialSchemaToTableSuggestions = (schema: PartialSchema): TableSug
return null
}
const relationships = Array.isArray(table.relationships)
? (table.relationships
.filter(
(
relationship
): relationship is NonNullable<PartialTable['relationships']>[number] & {
from: string
to: string
type: TableRelationship['type']
} =>
!!relationship &&
typeof relationship.from === 'string' &&
typeof relationship.to === 'string' &&
typeof relationship.type === 'string'
)
.map((relationship) => ({
from: relationship.from,
to: relationship.to,
type: relationship.type,
})) as TableSuggestion['relationships'])
: undefined
return {
tableName,
fields,
rationale: typeof table.description === 'string' ? table.description : undefined,
source: TableSource.AI,
relationships: relationships && relationships.length > 0 ? relationships : undefined,
}
})
.filter(isNotNull)
@@ -12,16 +12,6 @@ const ColumnSchema = z.object({
name: z.string().describe('The column name in snake_case'),
type: z.string().describe('PostgreSQL data type (e.g., bigint, text, timestamp with time zone)'),
isPrimary: z.boolean().optional().nullable().describe('Whether this is a primary key'),
isForeign: z.boolean().optional().nullable().describe('Whether this is a foreign key'),
references: z
.object({
table: z.string(),
column: z.string(),
})
.passthrough()
.optional()
.nullable()
.describe('Foreign key reference details'),
isNullable: z.boolean().optional().nullable().describe('Whether the column can be null'),
defaultValue: z.string().optional().nullable().describe('Default value or expression'),
isUnique: z
@@ -35,11 +25,6 @@ const TableSchema = z.object({
name: z.string().describe('The table name in snake_case'),
description: z.string().describe('A brief description of what this table stores'),
columns: z.array(ColumnSchema).describe('Array of columns in the table'),
relationships: z
.union([z.record(z.any()), z.array(z.any())])
.optional()
.nullable()
.describe('Foreign key relationships'),
})
const ResponseSchema = z.object({
@@ -110,8 +95,7 @@ const handlePost = async (req: NextApiRequest, res: NextApiResponse) => {
- Use 'text' for string data, 'timestamptz' for timestamps
- Use snake_case naming consistently
- Add created_at, updated_at timestamps with type: 'timestamptz' and defaultValue: 'now()'
- Reference auth.users(id) for user relations when appropriate
- For foreign key columns, use references as an object: { "table": "table_name", "column": "column_name" }
- Do NOT generate foreign key constraints or relationships
- Keep descriptions brief (one sentence)
- Focus on the most essential tables only