@api-buddy/schema
v3.0.0
Published
Core schema definition and validation for API Buddy
Maintainers
Readme
@api-buddy/schema
Core schema definition, validation, and type generation for API Buddy. This package provides the foundation for defining your application's data model, validating schemas, and generating TypeScript types.
Features
- Type-Safe Schema Definition: Define your data model with TypeScript types
- Runtime Validation: Validate schemas at runtime using Zod
- Type Generation: Generate TypeScript types from your schema
- Schema Diffing: Compare schemas and generate migration steps
- Relation Support: Define relationships between models
- Enum Support: Define and validate enums
- Extensible: Add custom validators and field types
- Input Type Generation: Automatically generate input types for your models
- Relation Types: Generate proper TypeScript types for model relations
Installation
npm install @api-buddy/schema
# or
yarn add @api-buddy/schema
# or
pnpm add @api-buddy/schemaUsage
Basic Usage
import { typeGenerator, Schema } from '@api-buddy/schema';
// Define your schema
const schema: Schema = {
models: {
User: {
fields: {
id: { type: 'ID', required: true },
name: { type: 'String', required: true },
email: { type: 'String', required: true, unique: true },
createdAt: { type: 'Date', required: true }
}
}
}
};
// Generate TypeScript types
const typeDefinitions = await typeGenerator.generateTypes(schema);
console.log(typeDefinitions);Using with Custom Type Mappings
import { typeGenerator } from '@api-buddy/schema';
// Create a custom type generator with custom mappings
const customGenerator = new TypeGenerator({
typeMapping: {
// Map custom types to TypeScript types
'UUID': 'string',
'JSON': 'Record<string, any>',
'DateTime': 'Date'
},
strictNullChecks: true
});
// Use the custom generator
const types = await customGenerator.generateTypes(schema);Extending with Plugins
import { pluginManager, typeGenerator } from '@api-buddy/schema';
// Create a plugin that adds a header to generated types
const headerPlugin = {
name: 'header-plugin',
hooks: {
afterTypegen: (output: string) => {
return `// Auto-generated by API Buddy
// DO NOT EDIT DIRECTLY
${output}`;
}
}
};
// Register the plugin
pluginManager.register(headerPlugin);
// Now all type generation will include the header
const types = await typeGenerator.generateTypes(schema);Defining a Schema
import { Schema } from '@api-buddy/schema';
const schema: Schema = {
models: {
User: {
fields: {
id: { type: 'ID', required: true },
email: { type: 'String', required: true, unique: true },
name: { type: 'String', required: true },
role: { type: 'UserRole', required: true },
posts: {
type: 'Relation',
relation: {
model: 'Post',
type: 'hasMany',
},
},
},
timestamps: true,
},
Post: {
fields: {
id: { type: 'ID', required: true },
title: { type: 'String', required: true },
content: { type: 'String' },
published: { type: 'Boolean', default: false },
author: {
type: 'Relation',
relation: {
model: 'User',
type: 'belongsTo',
foreignKey: 'authorId',
},
},
},
},
},
enums: {
UserRole: ['ADMIN', 'EDITOR', 'USER'],
},
};Validating a Schema
import { validateSchema } from '@api-buddy/schema';
const { valid, errors } = validateSchema(schema);
if (!valid) {
console.error('Schema validation failed:', errors);
}Using Schema Helpers
import { getModelRelations, isRelationField } from '@api-buddy/schema';
// Get all relations for a model
const relations = getModelRelations(schema, 'User');
// Check if a field is a relation
const isRelation = isRelationField(schema.models.User.fields.posts);Schema Validation
Basic Validation
import { validateSchema } from '@api-buddy/schema';
const { valid, errors } = validateSchema(schema);
if (!valid) {
console.error('Schema validation failed:', errors);
}Type Generation
Basic Type Generation
import { TypeGenerator } from '@api-buddy/schema';
const typeGenerator = new TypeGenerator();
const typeDefinitions = typeGenerator.generateTypes(schema);
// Write to a file
import { writeFileSync } from 'fs';
writeFileSync('generated-types.ts', typeDefinitions);Custom Type Mappings
You can provide custom type mappings for your schema types:
const typeGenerator = new TypeGenerator({
// Map custom types to TypeScript types
UUID: 'string',
DateTime: 'Date',
// Add custom type mappings as needed
});Schema Diffing and Migrations
Comparing Schemas
import { diffSchemas, generateMigrationSteps } from '@api-buddy/schema';
// Compare two schemas
const diff = diffSchemas(oldSchema, newSchema);
// Generate migration steps
const migrationSteps = generateMigrationSteps(diff);
console.log('Migration steps:', migrationSteps);Example Migration Output
[
"// Create new models: User, Post",
"// TODO: Implement create table statements",
"// Add fields to User: email, name",
"// TODO: Implement add column statements"
]Advanced Usage
Custom Type Import Handling
// Add custom type imports
const typeGenerator = new TypeGenerator();
typeGenerator.addTypeImport('Date', 'luxon', 'DateTime');
typeGenerator.addTypeImport('ObjectId', 'mongodb');Schema Versioning
import { getSchemaVersion, isCompatible } from '@api-buddy/schema';
// Get the current schema version
const version = getSchemaVersion(schema);
// Check if two schemas are compatible
const compatible = isCompatible(oldSchema, newSchema);TypeScript Integration
The generated types integrate seamlessly with TypeScript:
// Example of using generated types
interface User {
id: string | number;
name: string;
email: string;
posts?: Post[];
}
interface Post {
id: string | number;
title: string;
content: string;
author: User | User['id'];
tags?: string[];
}
// Input types are also generated
interface UserInput {
name?: string;
email?: string;
// ... other fields
}API Reference
Types
Schema: The root schema typeModelDefinition: Definition of a modelFieldDefinition: Definition of a fieldFieldType: Supported field types
Functions
validateSchema(schema: unknown): Validate a schemaparseSchema(schema: unknown): Parse and validate a schemagetModelRelations(schema, modelName): Get all relations for a modelisRelationField(field): Check if a field is a relationgetPrimaryKeyField(model): Get the primary key field of a modelgetTableName(modelName, modelDef): Get the table name for a model
License
MIT
