{"_id":"@api-buddy/schema","_rev":"4-b436a001d058ba58c8defe60ae76244a","name":"@api-buddy/schema","dist-tags":{"latest":"3.0.0"},"versions":{"0.4.129":{"name":"@api-buddy/schema","version":"0.4.129","keywords":["api-buddy","schema","validation","typescript"],"author":{"name":"API Buddy Team"},"license":"MIT","_id":"@api-buddy/schema@0.4.129","maintainers":[{"name":"iamtomhanks","email":"brechanson@gmail.com"}],"dist":{"shasum":"7fa852d60c3029f85a5d4e529388a5a36790f41f","tarball":"https://registry.npmjs.org/@api-buddy/schema/-/schema-0.4.129.tgz","fileCount":134,"integrity":"sha512-e0Szlx1I/MhDxHJmbs5cr9H8ji61WKPzvypyzgLl/CwFV1F06PZIFvdSYXB8UGJcMY8NUb3wxRvvgijiT0vNDw==","signatures":[{"sig":"MEYCIQDN6xb5nwi/gpZhPwVFiZ2Y6j2LmVfW36DB83AnQuq/0wIhAM3KOyCjJkJ9NuUYPbEbNzGewak1D+as4WTFrq4+n8K7","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":450244},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"e73a0282c5f5196e3f5dfacd1e7980b64e8e6b4b","scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","test":"jest","build":"pnpm clean && pnpm build:types && pnpm build:esm","clean":"rm -rf dist","build:esm":"tsc -p tsconfig.build.json --module NodeNext --moduleResolution NodeNext --outDir dist/esm","postbuild":"node scripts/link-types.js","build:types":"tsc -p tsconfig.build.json --emitDeclarationOnly --declaration --outDir dist/types --module NodeNext --moduleResolution NodeNext","test:coverage":"jest --coverage"},"_npmUser":{"name":"iamtomhanks","email":"brechanson@gmail.com"},"_npmVersion":"9.8.1","description":"Core schema definition and validation for API Buddy","directories":{},"_nodeVersion":"18.18.0","dependencies":{"zod":"^3.22.4","chalk":"^4.1.2","deep-diff":"^1.0.2","pluralize":"^8.0.0","change-case":"^4.1.2","@api-buddy/types":"^0.4.129","@api-buddy/plugin-utils":"^0.4.129"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.55.0","ts-jest":"^29.1.1","fs-extra":"^11.3.0","prettier":"^3.1.1","typescript":"^5.3.3","@types/jest":"^29.5.11","@types/node":"^20.10.5","@types/change-case":"^2.3.5","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.2","@typescript-eslint/parser":"^6.13.2","@typescript-eslint/eslint-plugin":"^6.13.2"},"peerDependencies":{"typescript":">=4.9.0"},"_npmOperationalInternal":{"tmp":"tmp/schema_0.4.129_1749832983380_0.8186750104975236","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@api-buddy/schema","version":"1.0.0","keywords":["api-buddy","schema","validation","typescript"],"author":{"name":"API Buddy Team"},"license":"MIT","_id":"@api-buddy/schema@1.0.0","maintainers":[{"name":"iamtomhanks","email":"brechanson@gmail.com"}],"dist":{"shasum":"a70a5e6e6f90b8b058d0cdc31e488bcafb91aea9","tarball":"https://registry.npmjs.org/@api-buddy/schema/-/schema-1.0.0.tgz","fileCount":54,"integrity":"sha512-8SmPWEx/cBx7iiPHQWeU1SwdibrDCPTpd4GBVv4GFUOpDlpIDjqqApTZr2hJpKfsrJWEQdTRHw8QBPcKLSeq2w==","signatures":[{"sig":"MEQCIE+nGCICXTyxpXeVPUcn1M4BiMgVymD/fPU0ro6Kc4yLAiBTZyJubhFk4O2r6xqE7wOVz6gxtl5bGR7qFK3HNe+PMw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":438072},"main":"dist/index.js","type":"module","_from":"file:api-buddy-schema-1.0.0.tgz","types":"dist/index.d.ts","module":"dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","test":"NODE_OPTIONS=--experimental-vm-modules jest --config=jest.config.mjs","build":"pnpm clean && tsup","clean":"rimraf dist","format":"prettier --write \"src/**/*.{ts,tsx}\"","prebuild":"node -e \"const { execSync } = require('child_process'); const path = require('path'); const fs = require('fs'); let root = process.cwd(); while (root !== '/' && !fs.existsSync(path.join(root, 'pnpm-workspace.yaml'))) { root = path.dirname(root); } if (root === '/') { console.error('❌ Could not find project root directory'); process.exit(1); } require(path.join(root, 'scripts/ensure-tsup-config.js'));\"","postbuild":"node ../../../scripts/link-types.js","type-check":"tsc --noEmit","test:coverage":"NODE_OPTIONS=--experimental-vm-modules jest --config=jest.config.mjs --coverage"},"_npmUser":{"name":"iamtomhanks","email":"brechanson@gmail.com"},"_resolved":"/private/var/folders/w3/00m0j5k95zjfx4vwz3csj_vc0000gn/T/ba3d32cb05fdc3c98410039725aa7746/api-buddy-schema-1.0.0.tgz","_integrity":"sha512-8SmPWEx/cBx7iiPHQWeU1SwdibrDCPTpd4GBVv4GFUOpDlpIDjqqApTZr2hJpKfsrJWEQdTRHw8QBPcKLSeq2w==","_npmVersion":"9.8.1","description":"Core schema definition and validation for API Buddy","directories":{},"_nodeVersion":"18.18.0","dependencies":{"zod":"^3.22.4","chalk":"^4.1.2","deep-diff":"^1.0.2","pluralize":"^8.0.0","change-case":"^4.1.2","@api-buddy/types":"1.0.0","@api-buddy/plugin-utils":"1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","tsup":"^8.5.0","eslint":"^8.55.0","rimraf":"^5.0.5","ts-jest":"^29.1.1","fs-extra":"^11.3.0","prettier":"^3.1.1","typescript":"^5.3.3","@types/jest":"^29.5.11","@types/node":"^20.10.5","@types/change-case":"^2.3.5","@api-buddy/tsup-config":"1.0.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.2","@typescript-eslint/parser":"^6.13.2","@typescript-eslint/eslint-plugin":"^6.13.2"},"peerDependencies":{"typescript":">=4.9.0"},"_npmOperationalInternal":{"tmp":"tmp/schema_1.0.0_1750087967470_0.382867029745694","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@api-buddy/schema","version":"2.0.0","keywords":["api-buddy","schema","validation","typescript"],"author":{"name":"API Buddy Team"},"license":"MIT","_id":"@api-buddy/schema@2.0.0","maintainers":[{"name":"iamtomhanks","email":"brechanson@gmail.com"}],"dist":{"shasum":"ba910bf9198eb150b242b5e3cfd9d78f4ebd33f5","tarball":"https://registry.npmjs.org/@api-buddy/schema/-/schema-2.0.0.tgz","fileCount":54,"integrity":"sha512-VRKl/adv03wbumJDmAkpfkaM7EE79S8AuYn9IOm02iQiIDGQMCl3zdLPXQIn2MZIPrkpX48FYwfTtoSWjP+q+w==","signatures":[{"sig":"MEUCIAgXRxpj8drRvjRle563dg+r68DTpHuJKnJnPnUkd10AAiEAk1FMCGX6KYEZap6vSaxNXvmwNG32X45/EsweEEBymHo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":438072},"main":"dist/index.js","type":"module","_from":"file:api-buddy-schema-2.0.0.tgz","types":"dist/index.d.ts","module":"dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","test":"NODE_OPTIONS=--experimental-vm-modules jest --config=jest.config.mjs","build":"pnpm clean && tsup","clean":"rimraf dist","format":"prettier --write \"src/**/*.{ts,tsx}\"","prebuild":"node -e \"const { execSync } = require('child_process'); const path = require('path'); const fs = require('fs'); let root = process.cwd(); while (root !== '/' && !fs.existsSync(path.join(root, 'pnpm-workspace.yaml'))) { root = path.dirname(root); } if (root === '/') { console.error('❌ Could not find project root directory'); process.exit(1); } require(path.join(root, 'scripts/ensure-tsup-config.js'));\"","postbuild":"node ../../../scripts/link-types.js","type-check":"tsc --noEmit","test:coverage":"NODE_OPTIONS=--experimental-vm-modules jest --config=jest.config.mjs --coverage"},"_npmUser":{"name":"iamtomhanks","email":"brechanson@gmail.com"},"_resolved":"/private/var/folders/w3/00m0j5k95zjfx4vwz3csj_vc0000gn/T/af3f7ce0e4ec0e3e3bad18fa82d1c55f/api-buddy-schema-2.0.0.tgz","_integrity":"sha512-VRKl/adv03wbumJDmAkpfkaM7EE79S8AuYn9IOm02iQiIDGQMCl3zdLPXQIn2MZIPrkpX48FYwfTtoSWjP+q+w==","_npmVersion":"9.8.1","description":"Core schema definition and validation for API Buddy","directories":{},"_nodeVersion":"18.18.0","dependencies":{"zod":"^3.22.4","chalk":"^4.1.2","deep-diff":"^1.0.2","pluralize":"^8.0.0","change-case":"^4.1.2","@api-buddy/types":"2.0.0","@api-buddy/plugin-utils":"2.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","tsup":"^8.5.0","eslint":"^8.55.0","rimraf":"^5.0.5","ts-jest":"^29.1.1","fs-extra":"^11.3.0","prettier":"^3.1.1","typescript":"^5.3.3","@types/jest":"^29.5.11","@types/node":"^20.10.5","@types/change-case":"^2.3.5","@api-buddy/tsup-config":"2.0.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.2","@typescript-eslint/parser":"^6.13.2","@typescript-eslint/eslint-plugin":"^6.13.2"},"peerDependencies":{"typescript":">=4.9.0"},"_npmOperationalInternal":{"tmp":"tmp/schema_2.0.0_1750103119636_0.9067347892419493","host":"s3://npm-registry-packages-npm-production"}},"3.0.0":{"name":"@api-buddy/schema","version":"3.0.0","description":"Core schema definition and validation for API Buddy","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"dependencies":{"chalk":"^4.1.2","change-case":"^4.1.2","deep-diff":"^1.0.2","pluralize":"^8.0.0","zod":"^3.22.4","@api-buddy/types":"4.0.0","@api-buddy/plugin-utils":"3.0.0"},"devDependencies":{"@types/change-case":"^2.3.5","@types/jest":"^29.5.11","@types/node":"^20.10.5","@typescript-eslint/eslint-plugin":"^6.13.2","@typescript-eslint/parser":"^6.13.2","eslint":"^8.55.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.1.2","fs-extra":"^11.3.0","jest":"^29.7.0","prettier":"^3.1.1","rimraf":"^5.0.5","ts-jest":"^29.1.1","tsup":"^8.5.0","typescript":"^5.3.3","@api-buddy/tsup-config":"3.0.0"},"peerDependencies":{"typescript":">=4.9.0"},"keywords":["api-buddy","schema","validation","typescript"],"author":{"name":"API Buddy Team"},"license":"MIT","scripts":{"clean":"rimraf dist","build":"pnpm clean && tsup","dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","test":"NODE_OPTIONS=--experimental-vm-modules jest --config=jest.config.mjs","test:coverage":"NODE_OPTIONS=--experimental-vm-modules jest --config=jest.config.mjs --coverage","postbuild":"node ../../../scripts/link-types.js","type-check":"tsc --noEmit","format":"prettier --write \"src/**/*.{ts,tsx}\"","prebuild":"node -e \"const { execSync } = require('child_process'); const path = require('path'); const fs = require('fs'); let root = process.cwd(); while (root !== '/' && !fs.existsSync(path.join(root, 'pnpm-workspace.yaml'))) { root = path.dirname(root); } if (root === '/') { console.error('❌ Could not find project root directory'); process.exit(1); } require(path.join(root, 'scripts/ensure-tsup-config.js'));\""},"_id":"@api-buddy/schema@3.0.0","_integrity":"sha512-xs4CNok90cTP9NLsRUdl0O3SDkWn+8vQHlfxyldwobx5MfF9Z/VGpK96NxyMHhQUWtf7v+mNx5fpOj20hUlNXg==","_resolved":"/private/var/folders/w3/00m0j5k95zjfx4vwz3csj_vc0000gn/T/318dd34f8de9628a72650a6986f3a552/api-buddy-schema-3.0.0.tgz","_from":"file:api-buddy-schema-3.0.0.tgz","_nodeVersion":"18.18.0","_npmVersion":"9.8.1","dist":{"integrity":"sha512-xs4CNok90cTP9NLsRUdl0O3SDkWn+8vQHlfxyldwobx5MfF9Z/VGpK96NxyMHhQUWtf7v+mNx5fpOj20hUlNXg==","shasum":"a38ec6b53f6ee8aafc009dce84a362d00d019361","tarball":"https://registry.npmjs.org/@api-buddy/schema/-/schema-3.0.0.tgz","fileCount":54,"unpackedSize":438072,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFF9ICBOiF8huAw8dl86rkPTarDIalqOSZ8OChJj8H7qAiEAzu2QBJs8WJUTyoCVkRILfHwVHx0p2aCJd5Dfji0rXZ8="}]},"_npmUser":{"name":"iamtomhanks","email":"brechanson@gmail.com","actor":{"name":"iamtomhanks","email":"brechanson@gmail.com","type":"user"}},"directories":{},"maintainers":[{"name":"iamtomhanks","email":"brechanson@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/schema_3.0.0_1751386865274_0.47383887026606586"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-13T16:43:03.263Z","modified":"2025-07-01T16:21:05.626Z","0.4.129":"2025-06-13T16:43:03.573Z","1.0.0":"2025-06-16T15:32:47.705Z","2.0.0":"2025-06-16T19:45:19.809Z","3.0.0":"2025-07-01T16:21:05.455Z"},"author":{"name":"API Buddy Team"},"license":"MIT","keywords":["api-buddy","schema","validation","typescript"],"description":"Core schema definition and validation for API Buddy","maintainers":[{"name":"iamtomhanks","email":"brechanson@gmail.com"}],"readme":"# @api-buddy/schema\n\nCore 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.\n\n## Features\n\n- **Type-Safe Schema Definition**: Define your data model with TypeScript types\n- **Runtime Validation**: Validate schemas at runtime using Zod\n- **Type Generation**: Generate TypeScript types from your schema\n- **Schema Diffing**: Compare schemas and generate migration steps\n- **Relation Support**: Define relationships between models\n- **Enum Support**: Define and validate enums\n- **Extensible**: Add custom validators and field types\n- **Input Type Generation**: Automatically generate input types for your models\n- **Relation Types**: Generate proper TypeScript types for model relations\n\n## Installation\n\n```bash\nnpm install @api-buddy/schema\n# or\nyarn add @api-buddy/schema\n# or\npnpm add @api-buddy/schema\n```\n\n## Usage\n\n### Basic Usage\n\n```typescript\nimport { typeGenerator, Schema } from '@api-buddy/schema';\n\n// Define your schema\nconst schema: Schema = {\n  models: {\n    User: {\n      fields: {\n        id: { type: 'ID', required: true },\n        name: { type: 'String', required: true },\n        email: { type: 'String', required: true, unique: true },\n        createdAt: { type: 'Date', required: true }\n      }\n    }\n  }\n};\n\n// Generate TypeScript types\nconst typeDefinitions = await typeGenerator.generateTypes(schema);\nconsole.log(typeDefinitions);\n```\n\n### Using with Custom Type Mappings\n\n```typescript\nimport { typeGenerator } from '@api-buddy/schema';\n\n// Create a custom type generator with custom mappings\nconst customGenerator = new TypeGenerator({\n  typeMapping: {\n    // Map custom types to TypeScript types\n    'UUID': 'string',\n    'JSON': 'Record<string, any>',\n    'DateTime': 'Date'\n  },\n  strictNullChecks: true\n});\n\n// Use the custom generator\nconst types = await customGenerator.generateTypes(schema);\n```\n\n### Extending with Plugins\n\n```typescript\nimport { pluginManager, typeGenerator } from '@api-buddy/schema';\n\n// Create a plugin that adds a header to generated types\nconst headerPlugin = {\n  name: 'header-plugin',\n  hooks: {\n    afterTypegen: (output: string) => {\n      return `// Auto-generated by API Buddy\n// DO NOT EDIT DIRECTLY\n\n${output}`;\n    }\n  }\n};\n\n// Register the plugin\npluginManager.register(headerPlugin);\n\n// Now all type generation will include the header\nconst types = await typeGenerator.generateTypes(schema);\n```\n\n### Defining a Schema\n\n```typescript\nimport { Schema } from '@api-buddy/schema';\n\nconst schema: Schema = {\n  models: {\n    User: {\n      fields: {\n        id: { type: 'ID', required: true },\n        email: { type: 'String', required: true, unique: true },\n        name: { type: 'String', required: true },\n        role: { type: 'UserRole', required: true },\n        posts: {\n          type: 'Relation',\n          relation: {\n            model: 'Post',\n            type: 'hasMany',\n          },\n        },\n      },\n      timestamps: true,\n    },\n    Post: {\n      fields: {\n        id: { type: 'ID', required: true },\n        title: { type: 'String', required: true },\n        content: { type: 'String' },\n        published: { type: 'Boolean', default: false },\n        author: {\n          type: 'Relation',\n          relation: {\n            model: 'User',\n            type: 'belongsTo',\n            foreignKey: 'authorId',\n          },\n        },\n      },\n    },\n  },\n  enums: {\n    UserRole: ['ADMIN', 'EDITOR', 'USER'],\n  },\n};\n```\n\n### Validating a Schema\n\n```typescript\nimport { validateSchema } from '@api-buddy/schema';\n\nconst { valid, errors } = validateSchema(schema);\n\nif (!valid) {\n  console.error('Schema validation failed:', errors);\n}\n```\n\n### Using Schema Helpers\n\n```typescript\nimport { getModelRelations, isRelationField } from '@api-buddy/schema';\n\n// Get all relations for a model\nconst relations = getModelRelations(schema, 'User');\n\n// Check if a field is a relation\nconst isRelation = isRelationField(schema.models.User.fields.posts);\n```\n\n## Schema Validation\n\n### Basic Validation\n\n```typescript\nimport { validateSchema } from '@api-buddy/schema';\n\nconst { valid, errors } = validateSchema(schema);\n\nif (!valid) {\n  console.error('Schema validation failed:', errors);\n}\n```\n\n## Type Generation\n\n### Basic Type Generation\n\n```typescript\nimport { TypeGenerator } from '@api-buddy/schema';\n\nconst typeGenerator = new TypeGenerator();\nconst typeDefinitions = typeGenerator.generateTypes(schema);\n\n// Write to a file\nimport { writeFileSync } from 'fs';\nwriteFileSync('generated-types.ts', typeDefinitions);\n```\n\n### Custom Type Mappings\n\nYou can provide custom type mappings for your schema types:\n\n```typescript\nconst typeGenerator = new TypeGenerator({\n  // Map custom types to TypeScript types\n  UUID: 'string',\n  DateTime: 'Date',\n  // Add custom type mappings as needed\n});\n```\n\n## Schema Diffing and Migrations\n\n### Comparing Schemas\n\n```typescript\nimport { diffSchemas, generateMigrationSteps } from '@api-buddy/schema';\n\n// Compare two schemas\nconst diff = diffSchemas(oldSchema, newSchema);\n\n// Generate migration steps\nconst migrationSteps = generateMigrationSteps(diff);\n\nconsole.log('Migration steps:', migrationSteps);\n```\n\n### Example Migration Output\n\n```typescript\n[\n  \"// Create new models: User, Post\",\n  \"// TODO: Implement create table statements\",\n  \"// Add fields to User: email, name\",\n  \"// TODO: Implement add column statements\"\n]\n```\n\n## Advanced Usage\n\n### Custom Type Import Handling\n\n```typescript\n// Add custom type imports\nconst typeGenerator = new TypeGenerator();\ntypeGenerator.addTypeImport('Date', 'luxon', 'DateTime');\ntypeGenerator.addTypeImport('ObjectId', 'mongodb');\n```\n\n### Schema Versioning\n\n```typescript\nimport { getSchemaVersion, isCompatible } from '@api-buddy/schema';\n\n// Get the current schema version\nconst version = getSchemaVersion(schema);\n\n// Check if two schemas are compatible\nconst compatible = isCompatible(oldSchema, newSchema);\n```\n\n## TypeScript Integration\n\nThe generated types integrate seamlessly with TypeScript:\n\n```typescript\n// Example of using generated types\ninterface User {\n  id: string | number;\n  name: string;\n  email: string;\n  posts?: Post[];\n}\n\ninterface Post {\n  id: string | number;\n  title: string;\n  content: string;\n  author: User | User['id'];\n  tags?: string[];\n}\n\n// Input types are also generated\ninterface UserInput {\n  name?: string;\n  email?: string;\n  // ... other fields\n}\n```\n\n## API Reference\n\n### Types\n\n- `Schema`: The root schema type\n- `ModelDefinition`: Definition of a model\n- `FieldDefinition`: Definition of a field\n- `FieldType`: Supported field types\n\n### Functions\n\n- `validateSchema(schema: unknown)`: Validate a schema\n- `parseSchema(schema: unknown)`: Parse and validate a schema\n- `getModelRelations(schema, modelName)`: Get all relations for a model\n- `isRelationField(field)`: Check if a field is a relation\n- `getPrimaryKeyField(model)`: Get the primary key field of a model\n- `getTableName(modelName, modelDef)`: Get the table name for a model\n\n## License\n\nMIT\n","readmeFilename":"README.md"}