@mindmakr/gs-websdk
Version:
Web SDK for Guru SaaS System - Complete JavaScript/TypeScript SDK for building applications with dynamic schema management
1,139 lines (1,021 loc) • 27.1 kB
Markdown
# Schema Management Guide
This guide provides comprehensive information about working with dynamic schemas in the Guru SaaS system, including schema structure, field types, validation, composition, and best practices.
## Table of Contents
- [Understanding Schema Structure](#understanding-schema-structure)
- [Field Types Reference](#field-types-reference)
- [Schema Validation](#schema-validation)
- [Template Composition](#template-composition)
- [Path-Based Organization](#path-based-organization)
- [Versioning & Lifecycle](#versioning--lifecycle)
- [AI-Powered Enhancement](#ai-powered-enhancement)
- [Translation & Internationalization](#translation--internationalization)
- [Best Practices](#best-practices)
## Understanding Schema Structure
### Basic JSON Schema Format
Guru SaaS uses an extended JSON Schema format with additional UI and layout properties:
```json
{
"type": "object",
"title": "Customer Profile",
"description": "Comprehensive customer information form",
"properties": {
"firstName": {
"type": "string",
"title": "First Name",
"description": "Customer's first name",
"minLength": 1,
"maxLength": 50
},
"email": {
"type": "string",
"format": "email",
"title": "Email Address",
"description": "Primary contact email"
},
"age": {
"type": "integer",
"title": "Age",
"minimum": 18,
"maximum": 120
},
"preferences": {
"type": "object",
"title": "Preferences",
"properties": {
"newsletter": {
"type": "boolean",
"title": "Subscribe to Newsletter",
"default": false
},
"contactMethod": {
"type": "string",
"title": "Preferred Contact Method",
"enum": ["email", "phone", "sms"],
"enumNames": ["Email", "Phone", "SMS"],
"default": "email"
}
}
}
},
"required": ["firstName", "email"],
"x-field-order": ["firstName", "email", "age", "preferences"]
}
```
### Extended Properties
Beyond standard JSON Schema, Guru SaaS supports additional properties:
#### UI Properties
```json
{
"fieldName": {
"type": "string",
"title": "Field Title",
"ui:widget": "textarea",
"ui:placeholder": "Enter your text here",
"ui:help": "This field accepts markdown formatting",
"ui:layout": {
"width": "full",
"height": "medium"
},
"ui:options": {
"rows": 4,
"emptyValue": ""
}
}
}
```
#### Layout Properties
```json
{
"layout": {
"width": "half", // quarter, half, three-quarter, full
"height": "medium", // small, medium, large
"group": "contact", // Group fields together
"conditional": { // Conditional display
"field": "hasPhone",
"operator": "equals",
"value": true
}
}
}
```
#### Enhancement Properties
```json
{
"enhancement": {
"icon": "user",
"placeholder": {
"en": "Enter your name",
"es": "Ingrese su nombre"
},
"helpText": {
"en": "Your full legal name",
"es": "Su nombre legal completo"
},
"styling": {
"variant": "outline",
"size": "lg",
"className": "custom-field"
},
"validation": [
{
"type": "required",
"message": {
"en": "This field is required",
"es": "Este campo es obligatorio"
}
}
]
}
}
```
## Field Types Reference
### Basic Fields
#### Text Input
```json
{
"type": "string",
"title": "Text Field",
"minLength": 1,
"maxLength": 255,
"pattern": "^[a-zA-Z0-9\\s]+$"
}
```
#### Text Area
```json
{
"type": "string",
"format": "textarea",
"title": "Description",
"maxLength": 1000,
"ui:widget": "textarea",
"ui:options": { "rows": 4 }
}
```
#### Number
```json
{
"type": "number",
"title": "Price",
"minimum": 0,
"maximum": 999999,
"multipleOf": 0.01
}
```
#### Boolean
```json
{
"type": "boolean",
"title": "Active",
"default": true
}
```
#### Date & Time
```json
{
"birthday": {
"type": "string",
"format": "date",
"title": "Date of Birth"
},
"appointmentTime": {
"type": "string",
"format": "datetime",
"title": "Appointment Time"
},
"workingHours": {
"type": "string",
"format": "time",
"title": "Working Hours"
}
}
```
### Selection Fields
#### Select Dropdown
```json
{
"type": "string",
"title": "Country",
"enum": ["US", "CA", "UK", "DE"],
"enumNames": ["United States", "Canada", "United Kingdom", "Germany"],
"default": "US"
}
```
#### Multi-Select
```json
{
"type": "array",
"title": "Skills",
"items": {
"type": "string",
"enum": ["javascript", "python", "java", "csharp"]
},
"uniqueItems": true,
"minItems": 1,
"maxItems": 5
}
```
#### Radio Buttons
```json
{
"type": "string",
"title": "Subscription Plan",
"enum": ["basic", "premium", "enterprise"],
"enumNames": ["Basic", "Premium", "Enterprise"],
"ui:widget": "radio"
}
```
#### Checkboxes
```json
{
"type": "array",
"title": "Interests",
"items": {
"type": "string",
"enum": ["sports", "music", "technology", "travel"]
},
"ui:widget": "checkboxes",
"uniqueItems": true
}
```
### Advanced Fields
#### File Upload
```json
{
"type": "string",
"format": "data-url",
"title": "Profile Picture",
"ui:widget": "file",
"accept": "image/*"
}
```
#### Image with URL or Upload
```json
{
"type": "string",
"format": "image-url-or-upload",
"title": "Product Image",
"ui:widget": "ImageInputWidget",
"accept": "image/*"
}
```
#### Rich Text Editor
```json
{
"type": "string",
"format": "richtext",
"title": "Product Description",
"ui:widget": "richtext",
"ui:layout": { "height": "large" }
}
```
#### Reference Field
```json
{
"type": "string",
"format": "reference",
"title": "Related Product",
"ui:widget": "ReferenceFieldWidget",
"referenceConfig": {
"entityType": "product",
"displayField": "name",
"searchFields": ["name", "sku"],
"allowEmpty": true,
"allowMultiSelect": false,
"filterBy": { "category": "electronics" }
}
}
```
#### Multi-Select Reference Field
```json
{
"type": "array",
"format": "reference",
"title": "Related Categories",
"ui:widget": "ReferenceFieldWidget",
"referenceConfig": {
"entityType": "category",
"displayField": "name",
"searchFields": ["name", "description"],
"allowEmpty": true,
"allowMultiSelect": true,
"filterBy": { "type": "product_category" }
}
}
```
#### Color Picker
```json
{
"type": "string",
"format": "color",
"title": "Brand Color",
"default": "#000000"
}
```
#### Navigation List
```json
{
"type": "array",
"title": "Menu Items",
"items": {
"type": "object",
"title": "Menu Item",
"properties": {
"text": {
"type": "string",
"title": "Link Text"
},
"url": {
"type": "string",
"format": "uri",
"title": "URL"
},
"target": {
"type": "string",
"title": "Target",
"enum": ["_self", "_blank"],
"default": "_self"
}
},
"required": ["text", "url"]
},
"ui:options": {
"addable": true,
"orderable": true,
"removable": true
}
}
```
### Layout Fields
#### Section Divider
```json
{
"type": "null",
"title": "Contact Information",
"description": "Please provide your contact details",
"ui:widget": "section"
}
```
## Schema Validation
### Built-in Validation Rules
#### String Validation
```json
{
"type": "string",
"minLength": 3,
"maxLength": 50,
"pattern": "^[a-zA-Z\\s]+$"
}
```
#### Number Validation
```json
{
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMinimum": 0,
"exclusiveMaximum": 100,
"multipleOf": 0.5
}
```
#### Array Validation
```json
{
"type": "array",
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
```
### Custom Validation Rules
```json
{
"fieldName": {
"type": "string",
"title": "Password",
"validation": [
{
"type": "min_length",
"value": 8,
"message": {
"en": "Password must be at least 8 characters long",
"es": "La contraseña debe tener al menos 8 caracteres"
}
},
{
"type": "regex",
"value": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]",
"message": {
"en": "Password must contain uppercase, lowercase, number, and special character",
"es": "La contraseña debe contener mayúsculas, minúsculas, números y caracteres especiales"
}
}
]
}
}
```
### Cross-Field Validation
```json
{
"password": {
"type": "string",
"title": "Password"
},
"confirmPassword": {
"type": "string",
"title": "Confirm Password",
"validation": [
{
"type": "field_equals",
"value": "password",
"message": {
"en": "Passwords must match",
"es": "Las contraseñas deben coincidir"
}
}
]
}
}
```
### Conditional Validation
```json
{
"hasPhone": {
"type": "boolean",
"title": "I have a phone number"
},
"phoneNumber": {
"type": "string",
"format": "phone",
"title": "Phone Number",
"dependencies": {
"hasPhone": true
},
"layout": {
"conditional": {
"field": "hasPhone",
"operator": "equals",
"value": true
}
}
}
}
```
## Template Composition
### Inheritance
Create base templates that can be extended:
```typescript
// Base template
const baseCustomerTemplate = {
type: "object",
title: "Base Customer",
properties: {
firstName: { type: "string", title: "First Name" },
lastName: { type: "string", title: "Last Name" },
email: { type: "string", format: "email", title: "Email" }
},
required: ["firstName", "lastName", "email"]
};
// Extended template
const premiumCustomerTemplate = await client.schema.createComposedTemplate(
baseTemplateId,
{
compositionRules: {
inherit: ["firstName", "lastName", "email"],
extend: [
{
key: "accountManager",
type: "string",
title: "Account Manager"
},
{
key: "creditLimit",
type: "number",
title: "Credit Limit",
minimum: 0
}
]
}
}
);
```
### Override and Extend
```typescript
const composedTemplate = await client.schema.createComposedTemplate(
baseTemplateId,
{
compositionRules: {
inherit: ["firstName", "lastName"],
override: {
email: {
type: "string",
format: "email",
title: "Business Email",
description: "Your company email address"
}
},
extend: [
{
key: "company",
type: "string",
title: "Company Name"
}
],
exclude: ["personalNotes"],
rename: {
"phoneNumber": "businessPhone"
}
},
conflictResolution: "merge"
}
);
```
### Composition Rules
```typescript
interface CompositionRules {
inherit?: string[]; // Fields to inherit from base
override?: Record<string, any>; // Fields to override
extend?: Array<{ // New fields to add
key: string;
type: string;
[key: string]: any;
}>;
exclude?: string[]; // Fields to exclude
rename?: Record<string, string>; // Field name mappings
}
```
## Path-Based Organization
### Hierarchical Structure
Organize templates using path-based hierarchy:
```
root/
├── ecommerce/
│ ├── products/
│ │ ├── catalog
│ │ ├── variants
│ │ └── inventory
│ ├── customers/
│ │ ├── profile
│ │ ├── preferences
│ │ └── billing
│ └── orders/
│ ├── checkout
│ ├── shipping
│ └── returns
└── hr/
├── employees/
│ ├── profile
│ ├── benefits
│ └── performance
└── recruiting/
├── application
├── interview
└── onboarding
```
### Working with Paths
```typescript
// Create template with path
const template = await client.schema.createSchemaTemplate({
name: "Product Catalog",
code: "product_catalog",
path: "root/ecommerce/products/catalog",
// ... other properties
});
// Navigate by path
const catalogTemplate = await client.schema.getSchemaTemplateByPath(
"root/ecommerce/products/catalog"
);
// Get children of a path
const productTemplates = await client.schema.getSchemaTemplateChildren(
"root/ecommerce/products"
);
// Move template to new path
await client.schema.moveSchemaTemplate(
template.id,
"root/ecommerce/inventory/products"
);
// Get virtual hierarchy
const hierarchy = await client.schema.getVirtualHierarchy();
```
### Virtual Hierarchy
The system automatically generates a virtual folder structure for navigation:
```typescript
interface VirtualHierarchyNode {
path: string;
name: string;
type: 'template' | 'folder';
templateId?: number;
depth: number;
hasChildren: boolean;
}
```
## Versioning & Lifecycle
### Version Management
```typescript
// Create new version
const version = await client.schema.createAdvancedSchemaTemplateVersion(
templateId,
{
version_number: "2.1.0",
semantic_version: "2.1.0",
schema_definition: updatedSchema,
change_description: "Added new customer preference fields",
version_type: "manual",
breaking_changes: false,
migration_required: false,
compatibility_notes: "Backward compatible with v2.0.x",
auto_publish_at: "2024-01-01T00:00:00Z"
}
);
// Get version history
const versions = await client.schema.getEnhancedVersionHistory(templateId);
// Compare versions
const comparison = await client.schema.getVersionComparison(
version1Id,
version2Id
);
// Rollback to previous version
const rollback = await client.schema.rollbackSchemaTemplateVersion(
templateId,
previousVersionId,
"Rollback due to validation issues"
);
```
### Template Lifecycle
Templates follow a defined lifecycle:
1. **Draft** - Under development
2. **Published** - Available for use
3. **Archived** - No longer active
```typescript
// Publish template
const published = await client.schema.publishSchemaTemplate(
templateId,
"2024-12-31T23:59:59Z" // Optional expiration
);
// Update status
const updated = await client.schema.updateSchemaTemplate(templateId, {
status: "archived"
});
```
## AI-Powered Enhancement
### Schema Generation
Generate complete schemas using AI:
```typescript
const aiSchema = await client.ai.generateSchema({
businessDescription: "Customer feedback form for restaurant service",
industry: "hospitality",
formType: "feedback",
requirements: [
"Must collect customer contact information",
"Need rating system for food, service, and ambiance",
"Should allow photo uploads for evidence",
"Include open-text feedback field"
],
language: "en"
});
// Execute the generated schema
const template = await client.ai.executeSchemaCreation(
aiSchema.schema,
{
templateName: "Restaurant Feedback Form",
templateCode: "restaurant_feedback",
category: "hospitality",
description: "Comprehensive customer feedback collection"
}
);
```
### Field Enhancement
Enhance individual fields with AI:
```typescript
// Get field name suggestions
const nameSuggestions = await client.ai.suggestFieldName({
fieldType: "email",
businessContext: "customer registration",
existingFields: ["firstName", "lastName"],
userIntent: "collect primary contact email"
});
// Get validation suggestions
const validationSuggestions = await client.ai.suggestValidation({
fieldName: "customerEmail",
fieldType: "email",
businessDomain: "e-commerce"
});
// Get field type suggestions
const typeSuggestions = await client.ai.suggestFieldType({
fieldName: "customerRating",
businessContext: "product review system"
});
```
### Context Analysis
Get AI recommendations for schema improvements:
```typescript
const analysis = await client.ai.analyzeContext({
businessDomain: "e-commerce",
existingSchema: currentSchema,
userGoals: ["increase conversion", "reduce form abandonment"],
targetAudience: "online shoppers"
});
console.log("Recommendations:", analysis.recommendations);
console.log("Insights:", analysis.insights);
```
## Translation & Internationalization
### Multi-Language Support
```typescript
// Define translatable fields
const schema = {
type: "object",
title: "Customer Survey",
properties: {
satisfaction: {
type: "string",
title: "Satisfaction Level",
enum: ["poor", "fair", "good", "excellent"],
enumNames: ["Poor", "Fair", "Good", "Excellent"]
}
}
};
// Add translations
await client.schema.updateSchemaTranslations(templateId, "es", {
"title": "Encuesta de Cliente",
"properties.satisfaction.title": "Nivel de Satisfacción",
"properties.satisfaction.enumNames.0": "Malo",
"properties.satisfaction.enumNames.1": "Regular",
"properties.satisfaction.enumNames.2": "Bueno",
"properties.satisfaction.enumNames.3": "Excelente"
});
// Get translations
const translations = await client.schema.getSchemaTranslations(
templateId,
"es"
);
```
### Supported Languages
```typescript
const languages = await client.schema.getSupportedLanguages();
// Example output:
[
{
id: 1,
code: "en",
name: "English",
native_name: "English",
is_rtl: false,
is_active: true,
sort_order: 1
},
{
id: 2,
code: "es",
name: "Spanish",
native_name: "Español",
is_rtl: false,
is_active: true,
sort_order: 2
}
]
```
## Best Practices
### Schema Design
1. **Keep schemas focused** - Each template should have a single, clear purpose
2. **Use descriptive names** - Field names and titles should be clear and meaningful
3. **Provide helpful descriptions** - Use description fields to guide users
4. **Group related fields** - Use sections and layout groups to organize forms
5. **Consider mobile users** - Use appropriate field widths and layouts
### Validation Strategy
1. **Validate early and often** - Use both client-side and server-side validation
2. **Provide clear error messages** - Make validation errors helpful and actionable
3. **Use progressive validation** - Validate fields as users complete them
4. **Consider user experience** - Don't overwhelm users with too many validation rules
### Performance Optimization
1. **Use field ordering** - Define explicit field order for consistent rendering
2. **Minimize required fields** - Only mark fields as required when absolutely necessary
3. **Optimize for common use cases** - Design schemas for the most frequent scenarios
4. **Cache frequently used templates** - Implement caching for better performance
### Maintenance and Evolution
1. **Version strategically** - Create new versions for significant changes
2. **Document changes** - Always include clear change descriptions
3. **Test thoroughly** - Validate schemas with real data before publishing
4. **Plan for migration** - Consider how existing data will work with new versions
5. **Archive obsolete templates** - Keep the system clean by archiving unused templates
### Security Considerations
1. **Sanitize input** - Always sanitize form data before storage
2. **Validate permissions** - Ensure users can only access appropriate templates
3. **Protect sensitive data** - Use appropriate field types for sensitive information
4. **Audit changes** - Track who makes changes to templates and when
### Example: Complete E-commerce Product Schema
```json
{
"type": "object",
"title": "Product Information",
"description": "Comprehensive product catalog entry",
"properties": {
"basic_info": {
"type": "null",
"title": "Basic Information",
"ui:widget": "section"
},
"name": {
"type": "string",
"title": "Product Name",
"description": "The display name for this product",
"minLength": 1,
"maxLength": 200,
"ui:layout": { "width": "full" }
},
"sku": {
"type": "string",
"title": "SKU",
"description": "Stock Keeping Unit - unique product identifier",
"pattern": "^[A-Z0-9-]+$",
"maxLength": 50,
"ui:layout": { "width": "half" }
},
"category": {
"type": "string",
"title": "Category",
"enum": ["electronics", "clothing", "books", "home", "sports"],
"enumNames": ["Electronics", "Clothing", "Books", "Home & Garden", "Sports"],
"ui:layout": { "width": "half" }
},
"description": {
"type": "string",
"format": "richtext",
"title": "Description",
"description": "Detailed product description with formatting",
"ui:widget": "richtext",
"ui:layout": { "width": "full", "height": "large" }
},
"pricing": {
"type": "null",
"title": "Pricing Information",
"ui:widget": "section"
},
"price": {
"type": "number",
"title": "Price",
"description": "Base price in USD",
"minimum": 0,
"format": "currency",
"ui:layout": { "width": "quarter" }
},
"salePrice": {
"type": "number",
"title": "Sale Price",
"description": "Discounted price (optional)",
"minimum": 0,
"format": "currency",
"ui:layout": { "width": "quarter" }
},
"costPrice": {
"type": "number",
"title": "Cost Price",
"description": "Internal cost for margin calculation",
"minimum": 0,
"format": "currency",
"ui:layout": { "width": "quarter" }
},
"taxable": {
"type": "boolean",
"title": "Taxable",
"description": "Is this product subject to sales tax?",
"default": true,
"ui:layout": { "width": "quarter" }
},
"inventory": {
"type": "null",
"title": "Inventory Management",
"ui:widget": "section"
},
"trackInventory": {
"type": "boolean",
"title": "Track Inventory",
"default": true,
"ui:layout": { "width": "quarter" }
},
"stockQuantity": {
"type": "integer",
"title": "Stock Quantity",
"minimum": 0,
"layout": {
"width": "quarter",
"conditional": {
"field": "trackInventory",
"operator": "equals",
"value": true
}
}
},
"lowStockThreshold": {
"type": "integer",
"title": "Low Stock Alert",
"description": "Alert when stock falls below this level",
"minimum": 0,
"default": 10,
"layout": {
"width": "quarter",
"conditional": {
"field": "trackInventory",
"operator": "equals",
"value": true
}
}
},
"allowBackorder": {
"type": "boolean",
"title": "Allow Backorder",
"description": "Allow orders when out of stock",
"default": false,
"layout": {
"width": "quarter",
"conditional": {
"field": "trackInventory",
"operator": "equals",
"value": true
}
}
},
"media": {
"type": "null",
"title": "Product Media",
"ui:widget": "section"
},
"images": {
"type": "array",
"title": "Product Images",
"description": "Upload or link product images",
"items": {
"type": "string",
"format": "image-url-or-upload",
"title": "Image"
},
"minItems": 1,
"maxItems": 10,
"ui:widget": "ImageInputWidget",
"ui:layout": { "width": "full" }
},
"specifications": {
"type": "null",
"title": "Specifications",
"ui:widget": "section"
},
"weight": {
"type": "number",
"title": "Weight (kg)",
"minimum": 0,
"ui:layout": { "width": "quarter" }
},
"dimensions": {
"type": "object",
"title": "Dimensions (cm)",
"properties": {
"length": { "type": "number", "title": "Length", "minimum": 0 },
"width": { "type": "number", "title": "Width", "minimum": 0 },
"height": { "type": "number", "title": "Height", "minimum": 0 }
},
"ui:layout": { "width": "three-quarter" }
},
"shipping": {
"type": "null",
"title": "Shipping Information",
"ui:widget": "section"
},
"shippingClass": {
"type": "string",
"title": "Shipping Class",
"enum": ["standard", "heavy", "fragile", "hazardous"],
"enumNames": ["Standard", "Heavy Item", "Fragile", "Hazardous"],
"default": "standard",
"ui:layout": { "width": "half" }
},
"freeShipping": {
"type": "boolean",
"title": "Free Shipping",
"default": false,
"ui:layout": { "width": "quarter" }
},
"isActive": {
"type": "boolean",
"title": "Active",
"description": "Is this product available for sale?",
"default": true,
"ui:layout": { "width": "quarter" }
}
},
"required": ["name", "sku", "category", "price", "images"],
"x-field-order": [
"basic_info", "name", "sku", "category", "description",
"pricing", "price", "salePrice", "costPrice", "taxable",
"inventory", "trackInventory", "stockQuantity", "lowStockThreshold", "allowBackorder",
"media", "images",
"specifications", "weight", "dimensions",
"shipping", "shippingClass", "freeShipping", "isActive"
]
}
```
This schema demonstrates:
- Section organization with dividers
- Conditional field display
- Various field types and formats
- Proper validation rules
- Layout specifications
- Logical field ordering
By following these patterns and best practices, you can create robust, user-friendly dynamic schemas that scale with your application needs.