Merge pull request #262 from johndoe6345789/codex/add-schema/default/forms,-components-and-validation

Refactor default schema into modular files
This commit is contained in:
2025-12-27 18:53:55 +00:00
committed by GitHub
5 changed files with 322 additions and 304 deletions
@@ -1,308 +1,6 @@
import type { SchemaConfig } from '../types/schema-types'
import { defaultApps } from './default/components'
export const defaultSchema: SchemaConfig = {
apps: [
{
name: 'blog',
label: 'Blog',
models: [
{
name: 'post',
label: 'Post',
labelPlural: 'Posts',
icon: 'Article',
listDisplay: ['title', 'author', 'status', 'publishedAt'],
listFilter: ['status', 'author'],
searchFields: ['title', 'content'],
ordering: ['-publishedAt'],
fields: [
{
name: 'id',
type: 'string',
label: 'ID',
required: true,
unique: true,
editable: false,
listDisplay: false,
},
{
name: 'title',
type: 'string',
label: 'Title',
required: true,
validation: {
minLength: 3,
maxLength: 200,
},
listDisplay: true,
searchable: true,
sortable: true,
},
{
name: 'slug',
type: 'string',
label: 'Slug',
required: true,
unique: true,
helpText: 'URL-friendly version of the title',
validation: {
pattern: '^[a-z0-9-]+$',
},
listDisplay: false,
sortable: true,
},
{
name: 'content',
type: 'text',
label: 'Content',
required: true,
helpText: 'Main post content',
listDisplay: false,
searchable: true,
},
{
name: 'excerpt',
type: 'text',
label: 'Excerpt',
required: false,
helpText: ['Short summary of the post', 'Used in list views and previews'],
validation: {
maxLength: 500,
},
listDisplay: false,
},
{
name: 'author',
type: 'relation',
label: 'Author',
required: true,
relatedModel: 'author',
listDisplay: true,
sortable: true,
},
{
name: 'status',
type: 'select',
label: 'Status',
required: true,
default: 'draft',
choices: [
{ value: 'draft', label: 'Draft' },
{ value: 'published', label: 'Published' },
{ value: 'archived', label: 'Archived' },
],
listDisplay: true,
sortable: true,
},
{
name: 'featured',
type: 'boolean',
label: 'Featured',
default: false,
helpText: 'Display on homepage',
listDisplay: true,
},
{
name: 'publishedAt',
type: 'datetime',
label: 'Published At',
required: false,
listDisplay: true,
sortable: true,
},
{
name: 'tags',
type: 'json',
label: 'Tags',
required: false,
helpText: 'JSON array of tag strings',
listDisplay: false,
},
{
name: 'views',
type: 'number',
label: 'Views',
default: 0,
validation: {
min: 0,
},
listDisplay: false,
},
],
},
{
name: 'author',
label: 'Author',
labelPlural: 'Authors',
icon: 'User',
listDisplay: ['name', 'email', 'active', 'createdAt'],
listFilter: ['active'],
searchFields: ['name', 'email'],
ordering: ['name'],
fields: [
{
name: 'id',
type: 'string',
label: 'ID',
required: true,
unique: true,
editable: false,
listDisplay: false,
},
{
name: 'name',
type: 'string',
label: 'Name',
required: true,
validation: {
minLength: 2,
maxLength: 100,
},
listDisplay: true,
searchable: true,
sortable: true,
},
{
name: 'email',
type: 'email',
label: 'Email',
required: true,
unique: true,
listDisplay: true,
searchable: true,
sortable: true,
},
{
name: 'bio',
type: 'text',
label: 'Bio',
required: false,
helpText: 'Author biography',
validation: {
maxLength: 1000,
},
listDisplay: false,
},
{
name: 'website',
type: 'url',
label: 'Website',
required: false,
listDisplay: false,
},
{
name: 'active',
type: 'boolean',
label: 'Active',
default: true,
listDisplay: true,
},
{
name: 'createdAt',
type: 'datetime',
label: 'Created At',
required: true,
editable: false,
listDisplay: true,
sortable: true,
},
],
},
],
},
{
name: 'ecommerce',
label: 'E-Commerce',
models: [
{
name: 'product',
label: 'Product',
labelPlural: 'Products',
icon: 'ShoppingCart',
listDisplay: ['name', 'price', 'stock', 'available'],
listFilter: ['available', 'category'],
searchFields: ['name', 'description'],
ordering: ['name'],
fields: [
{
name: 'id',
type: 'string',
label: 'ID',
required: true,
unique: true,
editable: false,
listDisplay: false,
},
{
name: 'name',
type: 'string',
label: 'Product Name',
required: true,
validation: {
minLength: 3,
maxLength: 200,
},
listDisplay: true,
searchable: true,
sortable: true,
},
{
name: 'description',
type: 'text',
label: 'Description',
required: false,
helpText: 'Product description',
listDisplay: false,
searchable: true,
},
{
name: 'price',
type: 'number',
label: 'Price',
required: true,
validation: {
min: 0,
},
listDisplay: true,
sortable: true,
},
{
name: 'stock',
type: 'number',
label: 'Stock',
required: true,
default: 0,
validation: {
min: 0,
},
listDisplay: true,
sortable: true,
},
{
name: 'category',
type: 'select',
label: 'Category',
required: true,
choices: [
{ value: 'electronics', label: 'Electronics' },
{ value: 'clothing', label: 'Clothing' },
{ value: 'books', label: 'Books' },
{ value: 'home', label: 'Home & Garden' },
{ value: 'toys', label: 'Toys' },
],
listDisplay: false,
sortable: true,
},
{
name: 'available',
type: 'boolean',
label: 'Available',
default: true,
listDisplay: true,
},
],
},
],
},
],
apps: defaultApps,
}
@@ -0,0 +1,54 @@
import type { AppSchema, ModelSchema } from '../../types/schema-types'
import { authorFields, postFields, productFields } from './forms'
export const blogModels: ModelSchema[] = [
{
name: 'post',
label: 'Post',
labelPlural: 'Posts',
icon: 'Article',
listDisplay: ['title', 'author', 'status', 'publishedAt'],
listFilter: ['status', 'author'],
searchFields: ['title', 'content'],
ordering: ['-publishedAt'],
fields: postFields,
},
{
name: 'author',
label: 'Author',
labelPlural: 'Authors',
icon: 'User',
listDisplay: ['name', 'email', 'active', 'createdAt'],
listFilter: ['active'],
searchFields: ['name', 'email'],
ordering: ['name'],
fields: authorFields,
},
]
export const ecommerceModels: ModelSchema[] = [
{
name: 'product',
label: 'Product',
labelPlural: 'Products',
icon: 'ShoppingCart',
listDisplay: ['name', 'price', 'stock', 'available'],
listFilter: ['available', 'category'],
searchFields: ['name', 'description'],
ordering: ['name'],
fields: productFields,
},
]
export const defaultApps: AppSchema[] = [
{
name: 'blog',
label: 'Blog',
models: blogModels,
},
{
name: 'ecommerce',
label: 'E-Commerce',
models: ecommerceModels,
},
]
@@ -0,0 +1,244 @@
import type { FieldSchema } from '../../types/schema-types'
import { authorValidations, postValidations, productValidations } from './validation'
export const postFields: FieldSchema[] = [
{
name: 'id',
type: 'string',
label: 'ID',
required: true,
unique: true,
editable: false,
listDisplay: false,
},
{
name: 'title',
type: 'string',
label: 'Title',
required: true,
validation: postValidations.title,
listDisplay: true,
searchable: true,
sortable: true,
},
{
name: 'slug',
type: 'string',
label: 'Slug',
required: true,
unique: true,
helpText: 'URL-friendly version of the title',
validation: postValidations.slug,
listDisplay: false,
sortable: true,
},
{
name: 'content',
type: 'text',
label: 'Content',
required: true,
helpText: 'Main post content',
listDisplay: false,
searchable: true,
},
{
name: 'excerpt',
type: 'text',
label: 'Excerpt',
required: false,
helpText: ['Short summary of the post', 'Used in list views and previews'],
validation: postValidations.excerpt,
listDisplay: false,
},
{
name: 'author',
type: 'relation',
label: 'Author',
required: true,
relatedModel: 'author',
listDisplay: true,
sortable: true,
},
{
name: 'status',
type: 'select',
label: 'Status',
required: true,
default: 'draft',
choices: [
{ value: 'draft', label: 'Draft' },
{ value: 'published', label: 'Published' },
{ value: 'archived', label: 'Archived' },
],
listDisplay: true,
sortable: true,
},
{
name: 'featured',
type: 'boolean',
label: 'Featured',
default: false,
helpText: 'Display on homepage',
listDisplay: true,
},
{
name: 'publishedAt',
type: 'datetime',
label: 'Published At',
required: false,
listDisplay: true,
sortable: true,
},
{
name: 'tags',
type: 'json',
label: 'Tags',
required: false,
helpText: 'JSON array of tag strings',
listDisplay: false,
},
{
name: 'views',
type: 'number',
label: 'Views',
default: 0,
validation: postValidations.views,
listDisplay: false,
},
]
export const authorFields: FieldSchema[] = [
{
name: 'id',
type: 'string',
label: 'ID',
required: true,
unique: true,
editable: false,
listDisplay: false,
},
{
name: 'name',
type: 'string',
label: 'Name',
required: true,
validation: authorValidations.name,
listDisplay: true,
searchable: true,
sortable: true,
},
{
name: 'email',
type: 'email',
label: 'Email',
required: true,
unique: true,
listDisplay: true,
searchable: true,
sortable: true,
},
{
name: 'bio',
type: 'text',
label: 'Bio',
required: false,
helpText: 'Author biography',
validation: authorValidations.bio,
listDisplay: false,
},
{
name: 'website',
type: 'url',
label: 'Website',
required: false,
listDisplay: false,
},
{
name: 'active',
type: 'boolean',
label: 'Active',
default: true,
listDisplay: true,
},
{
name: 'createdAt',
type: 'datetime',
label: 'Created At',
required: true,
editable: false,
listDisplay: true,
sortable: true,
},
]
export const productFields: FieldSchema[] = [
{
name: 'id',
type: 'string',
label: 'ID',
required: true,
unique: true,
editable: false,
listDisplay: false,
},
{
name: 'name',
type: 'string',
label: 'Product Name',
required: true,
validation: productValidations.name,
listDisplay: true,
searchable: true,
sortable: true,
},
{
name: 'description',
type: 'text',
label: 'Description',
required: false,
helpText: 'Product description',
listDisplay: false,
searchable: true,
},
{
name: 'price',
type: 'number',
label: 'Price',
required: true,
validation: productValidations.price,
listDisplay: true,
sortable: true,
},
{
name: 'stock',
type: 'number',
label: 'Stock',
required: true,
default: 0,
validation: productValidations.stock,
listDisplay: true,
sortable: true,
},
{
name: 'category',
type: 'select',
label: 'Category',
required: true,
choices: [
{ value: 'electronics', label: 'Electronics' },
{ value: 'clothing', label: 'Clothing' },
{ value: 'books', label: 'Books' },
{ value: 'home', label: 'Home & Garden' },
{ value: 'toys', label: 'Toys' },
],
listDisplay: false,
sortable: true,
},
{
name: 'available',
type: 'boolean',
label: 'Available',
default: true,
listDisplay: true,
},
]
@@ -0,0 +1,19 @@
import type { FieldSchema } from '../../types/schema-types'
export const postValidations: Record<string, FieldSchema['validation']> = {
title: { minLength: 3, maxLength: 200 },
slug: { pattern: '^[a-z0-9-]+$' },
excerpt: { maxLength: 500 },
views: { min: 0 },
}
export const authorValidations: Record<string, FieldSchema['validation']> = {
name: { minLength: 2, maxLength: 100 },
bio: { maxLength: 1000 },
}
export const productValidations: Record<string, FieldSchema['validation']> = {
name: { minLength: 3, maxLength: 200 },
price: { min: 0 },
stock: { min: 0 },
}
+3
View File
@@ -1,3 +1,6 @@
// Schema utilities exports
export * from './schema-utils'
export { defaultSchema } from './default-schema'
export * from './default/components'
export * from './default/forms'
export * from './default/validation'