Skip to content

Comments

feat: Add Standard Schema support for Zod/Valibot/ArkType collection definitions#23

Open
CaptnClaw wants to merge 12 commits intomizzle-dev:mainfrom
CaptnClaw:feature/standard-schema-support
Open

feat: Add Standard Schema support for Zod/Valibot/ArkType collection definitions#23
CaptnClaw wants to merge 12 commits intomizzle-dev:mainfrom
CaptnClaw:feature/standard-schema-support

Conversation

@CaptnClaw
Copy link
Contributor

Summary

This PR adds support for defining collections using Standard Schema-compatible libraries (Zod, Valibot, ArkType) instead of the built-in field builders.

What's New

Core Features

  • fromStandardSchema() - Low-level factory accepting any StandardSchemaV1 compliant schema
  • fromZod() - Convenience wrapper that extracts Zod defaults automatically
  • Type inference - Full TypeScript type inference from schemas via InferStandardSchema<T>
  • Runtime validation - Schemas validate data on insert/update with detailed error messages

Collection Options

All existing collection features work with Standard Schema collections:

  • publicId - Auto-generated public IDs with custom prefixes
  • softDelete - Soft delete with deleted/deletedAt fields
  • timestamps - Automatic createdAt/updatedAt tracking

Example Usage

import { z } from 'zod';
import { mizzle, fromZod } from '@mizzle-dev/orm';

const userSchema = z.object({
  email: z.string().email(),
  name: z.string(),
  role: z.enum(['user', 'admin']).default('user'),
});

const users = fromZod('users', userSchema, {
  publicId: 'user',
  softDelete: true,
});

Testing

  • Unit tests for all new modules (standard-schema.test.ts, from-zod.test.ts)
  • Integration tests for validation on insert/update
  • E2E tests covering full workflow with publicId, softDelete, and timestamps
  • All existing tests pass (backward compatibility verified)

Documentation

  • Comprehensive README section with usage examples
  • Migration guide for converting field builder definitions to Standard Schema
  • Full working example in examples/standard-schema-zod.ts

Backward Compatibility

This is a purely additive feature. Existing field builder API remains unchanged and fully supported.

- Add @standard-schema/spec as dependency
- Create src/types/standard-schema.ts with:
  - Re-export StandardSchemaV1 from spec package
  - IsStandardSchema<T> type guard
  - InferSSInput<T> for extracting input types
  - InferSSOutput<T> for extracting output types
- Export types from src/index.ts
- Add comprehensive type tests (17 tests)
- All 230 tests pass, typecheck and build pass
- Create src/collection/from-standard-schema.ts with:
  - fromStandardSchema<T>(name, schema, options?) factory function
  - SSCollectionDefinition<T> type with , ,
  - SSCollectionOptions interface (publicId, softDelete, timestamps, middlewares)
  - SSCollectionMeta<T> for runtime metadata access
  - isSSCollectionDefinition() type guard
  - ExtractSSDocument/Insert/Update helper types
  - Runtime Standard Schema compliance validation
- Export fromStandardSchema and related types from index.ts
- Add 35 comprehensive tests covering:
  - Basic factory functionality with any StandardSchemaV1 schema
  - Options handling (publicId, softDelete, timestamps)
  - Type inference for Document/Insert/Update types
  - Nested objects, transforms, optional/default fields
  - Extract type helpers
  - Type guard behavior
  - Realistic usage examples
  - Edge cases (empty schemas, deep nesting, unions, nullable)
…pdate operations

- Add SSValidationError class in src/errors/validation-error.ts
  - Contains issues array from Standard Schema validation
  - Includes getIssuesAtPath(), paths getter, and toJSON() helpers
- Modify CollectionFacade to validate data using Standard Schema
  - create() validates data before inserting (throws SSValidationError on failure)
  - Updates skip full validation since they're partial (known limitation)
  - Backward compatible: validation skipped for non-SS collections
- Add guards for SS collections in applyDefaults, applyPolicies, and hooks
- Export SSValidationError and ValidationIssue from main index
- Add comprehensive tests in standard-schema-validation.test.ts (20 tests)

Note: Update validation is intentionally skipped because Standard Schema
validates complete structures, but updates only contain changed fields.
Future enhancement could validate individual field types.
…pdate operations

- Fixed update validation: now validates fields present in update data
- For partial updates, filters issues to only report errors for fields being updated
- Allows partial updates (missing required fields) while catching invalid values
- updateOne/updateMany now properly reject invalid field values
- Added tests for:
  - updateOne rejecting invalid name, age, enum values
  - updateMany rejecting invalid values in bulk updates
  - SSValidationError includes correct issues for invalid updates
- All 312 tests pass, typecheck passes
- Extended SSCollectionOptions.softDelete to accept boolean | { field?: string }
- Added SSSoftDeleteConfig interface for normalized config
- Added softDeleteConfig to SSCollectionMeta (normalized at factory time)
- Updated fromStandardSchema to normalize softDelete options (default field: 'deletedAt')
- Updated getSoftDeleteField() in CollectionFacade to check SS collections
- Added applySoftDeleteFilter() to exclude soft-deleted documents from queries
- Updated findById, findOne, findMany, count to apply soft delete filter
- softDelete(id) sets the deletedAt timestamp instead of deleting
- restore(id) clears the deletedAt timestamp
- Default queries exclude documents where soft delete field is set
- Exported SSSoftDeleteConfig from index.ts

Tests: 22 tests in src/collection/__tests__/standard-schema-soft-delete.test.ts covering:
- fromStandardSchema options (softDelete: true, softDelete: { field })
- softDelete() and restore() operations
- Query filtering (findMany, findOne, findById, count exclude soft-deleted)
- Custom soft delete field name support
- Integration with publicId
- Hard delete vs soft delete behavior
- Extended SSCollectionOptions.timestamps to accept boolean or custom config
- Added SSTimestampsConfig interface with createdAt/updatedAt field names
- Added timestampsConfig to SSCollectionMeta (normalized at factory time)
- Default field names: 'createdAt' and 'updatedAt'
- applyDefaults sets createdAt to current Date on insert
- applyUpdateTimestamps sets updatedAt to current Date on update/updateMany
- Exported SSTimestampsConfig from index.ts
- 20 tests covering all acceptance criteria
…ction

- Create src/collection/from-zod.ts with Zod-specific collection factory
- extractZodDefaults() extracts .default() values from Zod schema
- applyZodDefaults() applies extracted defaults on insert
- ZodValidationError provides Zod-formatted error messages with format()/flatten()
- validateWithZod() uses Zod's safeParse for better error formatting
- Update CollectionFacade to use Zod-specific validation and defaults
- Export fromZod, ZodValidationError, and related utilities from index.ts
- Tests: 51 tests covering extraction, application, validation, and integration
…port

- Add comprehensive 'Standard Schema Support' section to README.md
- Document fromStandardSchema and fromZod functions with examples
- Create examples/standard-schema-zod.ts with full working example
- Document all options (publicId, softDelete, timestamps)
- Include migration guide from field builders to Standard Schema
- Add example to examples/README.md
- All public APIs already have JSDoc comments from prior stories
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant