Skip to content

feat: support for custom strings, numbers and booleans#131

Merged
Oudwins merged 11 commits intomasterfrom
feat/custom-types
Mar 16, 2025
Merged

feat: support for custom strings, numbers and booleans#131
Oudwins merged 11 commits intomasterfrom
feat/custom-types

Conversation

@Oudwins
Copy link
Owner

@Oudwins Oudwins commented Mar 16, 2025

Summary by CodeRabbit

  • New Features

    • Enhanced boolean validation with a new equality check for more precise comparisons.
    • Expanded schema flexibility by introducing generics for both boolean and string validators, and adding support for custom integer types.
    • Introduced custom interface schemas that enable robust data transformation, validation, and error handling.
  • Documentation

    • Updated validation guides to include examples of the new boolean equality check and enhanced schema capabilities.
    • Added new documentation on creating custom schemas, detailing methods and best practices for implementation.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 16, 2025

Walkthrough

The pull request updates schema types by introducing generics for booleans and strings. The BoolSchema and StringSchema types now accept generic parameters (constrained by boolean and string types, respectively) with corresponding method signature updates, including a new EQ method for boolean equality. Additionally, a new custom interface schema is introduced alongside comprehensive tests for custom integer and string types. Other files update struct tags, type definitions, utility type aliases, coercion functionality, and documentation to reflect these changes.

Changes

File(s) Change Summary
boolean.go
boolean_validate_test.go
Updated BoolSchema to use generics (T ~bool), modified fields and method signatures (e.g. Parse, Validate, Test, etc.), added a new EQ method, and updated tests to reference *BoolSchema[bool].
string.go
string_custom_test.go
Updated StringSchema to use generics (T ~string), revised method signatures for parsing, validation, transformation, and testing, and provided custom tests for a string-like type (Env).
custom.go Introduced a new CustomInterfaceSchema with associated definitions, methods (getType, setCoercer, Parse, Validate, process, and validate), and a constructor function to enable custom schema handling with robust validation and error processing.
numbers_custom_test.go Added a custom integer type (MyInt) and its corresponding NumberSchema tests covering coercion, parsing, validation, transformations, and comparison operations.
internals/tests.go Modified the LengthCapable interface by updating the string type constraint from string to ~string to accept any string-like type.
struct_test.go Updated struct tags (e.g. changed "tim" to "tim-1") and renamed type Custom to CustomType, including updating associated constant declarations to reflect the new type.
utils.go
utilsOptions_test.go
Added a type alias CoercerFunc = conf.CoercerFunc and updated the deprecation notice for TestFunc; introduced a new test (TestWithCoercer) to validate custom coercion logic for converting byte arrays to hexadecimal strings.
docs/docs/zog-schemas.md Expanded documentation with a new boolean validation method example z.Bool().EQ(true), demonstrating the equality check functionality added to the boolean schema.

Sequence Diagram(s)

sequenceDiagram
    participant C as Client
    participant CIS as CustomInterfaceSchema
    participant PT as PreTransform
    participant VT as Validation Tests
    participant POT as PostTransform

    C->>CIS: Parse(data)
    CIS->>PT: Apply PreTransform
    PT-->>CIS: Transformed data
    CIS->>VT: Run Validations
    VT-->>CIS: Return issues/success
    alt Validation Fails
        CIS->>CIS: Execute Catch/Fallback
    else
        CIS->>POT: Apply PostTransform
        POT-->>CIS: Finalized data
    end
    CIS-->>C: Return result or error list
Loading

Possibly related PRs

Poem

I'm a cheery rabbit in a code-filled glen,
Hopping through generics and schemas again.
Booleans and strings now dance generic and new,
Custom logic and tests form a vibrant crew.
I nibble on tags and types with delight,
Celebrating clear code in the soft spring light!

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61552ff and 94f9e37.

📒 Files selected for processing (11)
  • boolean.go (8 hunks)
  • boolean_validate_test.go (1 hunks)
  • custom.go (1 hunks)
  • docs/docs/zog-schemas.md (1 hunks)
  • internals/tests.go (1 hunks)
  • numbers_custom_test.go (1 hunks)
  • string.go (23 hunks)
  • string_custom_test.go (1 hunks)
  • struct_test.go (3 hunks)
  • utils.go (2 hunks)
  • utilsOptions_test.go (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (28)
docs/docs/zog-schemas.md (1)

150-150: Great addition of the EQ() method for boolean validation!

This new method complements the existing True() and False() validators by providing a more generic equality check. This is particularly useful when you need to validate against a boolean parameter rather than hardcoding the expected value.

boolean_validate_test.go (1)

105-105: Correctly updated the type signature to use the new generic BoolSchema.

The change from *BoolSchema to *BoolSchema[bool] properly reflects the introduction of generics for boolean schemas, ensuring type safety while maintaining backward compatibility.

utils.go (3)

6-6: Added necessary import for the conf package.

This import is needed to support the new CoercerFunc type alias.


40-41: Good addition of the CoercerFunc type alias.

This type alias improves code organization by centralizing the coercion function type definition, making it easier to use and understand throughout the codebase.


47-47: Clear deprecation notice replacing the previous warning.

The updated comment clearly marks TestFunc as deprecated and recommends using z.schema.TestFunc instead, providing a better migration path for users.

internals/tests.go (1)

33-33: Excellent improvement to the LengthCapable interface.

Changing string to ~string allows the interface to work with custom string types, not just the built-in string type. This is a key enhancement that enables the library to support custom string types while maintaining all the validation capabilities.

struct_test.go (3)

34-39: Field tags updated correctly in objTagged struct.

The update to the Tim field's tag from no tag to zog:"tim-1" is consistent with the PR objective of enhancing type handling and serialization. This change allows for more specific field mapping during serialization/deserialization.


62-67: Test data updated to match new struct tags.

The test data in TestStructTags has been appropriately updated to use "tim-1" as the key, which corresponds to the modified struct tag. This ensures the test correctly validates the struct tag behavior.


332-336: Type definition change from Custom to CustomType is well implemented.

The change from Custom to CustomType enhances type safety and makes the type naming more explicit. Constants are correctly updated to use the new type.

utilsOptions_test.go (1)

83-120: Well-structured test for byte array coercion functionality.

The new TestWithCoercer function effectively tests the custom coercer that converts byte arrays to hexadecimal strings. The test covers both direct conversion and usage within a struct context. The implementation is robust, handling null bytes correctly.

Two minor suggestions:

  1. Consider adding a test case with null bytes to explicitly verify that behavior.
  2. Consider moving the coercer function to a utility package if it's likely to be reused elsewhere.
numbers_custom_test.go (3)

11-31: Well-implemented custom integer type and schema creator.

The MyInt type and CustomInt function properly implement a custom integer type with appropriate coercion. The approach follows good practices for extending the schema system with custom types.


32-166: Comprehensive basic validation tests for custom integer type.

The test suite thoroughly covers the basic functionality including parsing, validation, error formatting, schema options, required/optional fields, defaults, error catching, and transformations. All tests are well-structured with clear assertions.


167-315: Complete coverage of comparison operations and additional validators.

The tests for numerical comparisons (OneOf, EQ, GT, GTE, LT, LTE) and custom test functions are thorough and well-implemented. The type checking in TestCustomNumberGetType ensures the schema maintains the correct type.

string_custom_test.go (4)

11-29: Clean implementation of custom string type with appropriate schema creator.

The Env type and MyStringSchema function provide a good example of how to implement custom string types. The coercer implementation correctly handles type conversion while maintaining error propagation.


31-55: Essential validation tests cover core functionality.

The basic tests for optional fields, required validation, default values, and catch behavior are well-implemented and ensure the fundamental functionality works correctly.


57-77: Transformation tests verify both pre and post processing.

The pre-transform and post-transform tests confirm that values can be manipulated both before and after validation, which is essential for flexible schema handling.


79-148: Comprehensive validation tests for string-specific validators.

The tests thoroughly cover string-specific validations including length constraints, content validation (contains, prefix, suffix), regex matching, enum validation (OneOf), and special formats (email, URL, UUID). This provides complete coverage of the string schema capabilities.

custom.go (1)

3-43: Consider removing or uncommenting the experimental code.

All lines in this section are commented out, indicating that you may be experimenting or deferring implementation. If these definitions are actually needed for schema usage or custom interface definitions, uncomment them and add tests; otherwise, consider removing them to avoid confusion or dead code.

Would you like me to search the codebase to see if these commented structs or functions are referenced elsewhere? If yes, I'll generate a shell script to verify their usage.

boolean.go (5)

9-10: Good interface conformance check.

Declaring var _ PrimitiveZogSchema[bool] = &BoolSchema[bool]{} confirms at compile-time that BoolSchema[bool] satisfies the PrimitiveZogSchema[bool] interface. No issues here.


11-19: Generic type constraint and pointer fields.

Defining type BoolSchema[T ~bool] struct { ... } for generics is a neat way to handle boolean-like types. However, storing defaultVal and catch as pointers can be cautious because:

  • If many BoolSchema instances are created, referencing pointers may add slight complexity or confusion when unwrapping values.
  • Ensure there's no concurrency scenario where these pointers are modified.

Otherwise, this approach is consistent with the rest of the code.


36-44: Constructor approach looks consistent.

The Bool(opts ...SchemaOption) function returns a *BoolSchema[bool] and applies options for further customization. This approach aligns well with a fluent schema-building pattern.


47-60: Parsing and validation flow delegation.

Both Parse and Validate methods delegate core logic to primitiveProcessor and primitiveValidator (via process and validate). This is a systematic approach for code reuse. Ensure:

  • The transformations and tests that rely on these calls are thoroughly covered by tests.
  • That any special-case overrides or expansions (e.g., custom boolean constraints) are properly tested as well.

Also applies to: 63-66, 68-81, 84-86


155-159: Equality checks are straightforward and clear.

True(), False(), and EQ(val T) all append equality tests. This is a simple, discoverable API for boolean constraints. Just ensure p.EQ[T] is robust for all forms of boolean-like inputs you plan to support.

Also applies to: 160-164, 165-168

string.go (5)

13-13: Generic type constraint for string-like types.

Switching to type StringSchema[T ~string] allows flexible usage of any type whose underlying type is string. Storing defaultVal and catch as pointers is consistent with the boolean schema, but watch for clarity when you unmarshal the values. Overall, this design parallels the boolean schema changes, maintaining consistency.

Also applies to: 20-28


108-119: Ensure casting safety in Trim pre-transform.

The snippet:

case T:
  return T(strings.TrimSpace(string(v))), nil

relies on T being convertible to string and vice versa. This should be safe given T ~string, but be mindful of potential edge cases with custom string types. No immediate issues, just a reminder to test thoroughly.


221-237: Robust email and URL validation checks.

The Email() and URL() methods parse the pointer to T and cast it to a string for regex or URL parsing checks. This approach looks correct; just ensure edge cases (e.g., empty strings, unusual URLs) are tested thoroughly.

Also applies to: 240-257


260-299: Substring and character checks appear correct.

The methods HasPrefix, HasSuffix, Contains, ContainsUpper, ContainsDigit, and ContainsSpecial each parse the pointer to T, then rely on strings or character checks. This pattern is clear and consistent. Verify boundary cases (e.g., empty or single-character strings) in your tests to ensure correct reporting of issues.

Also applies to: 301-320, 322-344, 346-370, 372-398


400-417: UUID and regex matching logic.

UUID() and Match(regex) likewise parse *T and run their respective checks. Your approach to handle parse failures with ok == false returning false is consistent. Confirm defensive tests exist for incorrectly structured data.

Also applies to: 419-438

custom.go Outdated
Comment on lines +45 to +214
// func (v *CustomInterfaceSchema) Parse(data any, destPtr any, options ...ExecOption) ZogIssueList {
// errs := p.NewErrsList()
// defer errs.Free()

// ctx := p.NewExecCtx(errs, conf.IssueFormatter)
// defer ctx.Free()
// for _, opt := range options {
// opt(ctx)
// }

// path := p.NewPathBuilder()
// defer path.Free()
// v.process(ctx.NewSchemaCtx(data, destPtr, path, v.getType()))

// return errs.List
// }

// func (v *CustomInterfaceSchema) process(ctx *p.SchemaCtx) {
// defer ctx.Free()
// canCatch := v.catch != nil
// // 4. postTransforms
// defer func() {
// // only run posttransforms on success
// if !ctx.HasErrored() {
// for _, fn := range v.postTransforms {
// err := fn(ctx.Val, ctx)
// if err != nil {
// ctx.AddIssue(ctx.IssueFromUnknownError(err))
// return
// }
// }
// }
// }()

// // 1. preTransforms
// for _, fn := range v.preTransforms {
// nVal, err := fn(ctx.Val, ctx)
// // bail if error in preTransform
// if err != nil {
// if canCatch {
// v.definition.SetValue(ctx.Val, v.catch)
// return
// }
// ctx.AddIssue(ctx.IssueFromUnknownError(err))
// return
// }
// v.definition.SetValue(ctx.Val, nVal)
// }

// // 2. cast data to string & handle default/required
// // Warning. This uses generic IsZeroValue because for Validate we treat zero values as invalid for required fields. This is different from Parse.
// isZeroVal := p.IsZeroValue(ctx.Val)

// if isZeroVal {
// if v.defaultVal != nil {
// v.definition.SetValue(ctx.Val, v.defaultVal)
// } else if v.required == nil {
// // This handles optional case
// return
// } else {
// // is required & zero value
// // required
// if v.catch != nil {
// v.definition.SetValue(ctx.Val, v.catch)
// return
// } else {
// ctx.AddIssue(ctx.IssueFromTest(v.required, ctx.Val))
// return
// }
// }
// }
// // 3. tests
// for _, test := range v.tests {
// if !test.ValidateFunc(ctx.Val, ctx) {
// // catching the first error if catch is set
// if canCatch {
// v.definition.SetValue(ctx.Val, v.catch)
// return
// }
// ctx.AddIssue(ctx.IssueFromTest(&test, ctx.Val))
// }
// }

// }

// // Validate Given string
// func (v *CustomInterfaceSchema) Validate(dataPtr any, options ...ExecOption) p.ZogIssueList {
// errs := p.NewErrsList()
// defer errs.Free()
// ctx := p.NewExecCtx(errs, conf.IssueFormatter)
// defer ctx.Free()
// for _, opt := range options {
// opt(ctx)
// }

// path := p.NewPathBuilder()
// defer path.Free()
// v.validate(ctx.NewSchemaCtx(dataPtr, dataPtr, path, v.getType()))
// return errs.List
// }

// // Internal function to validate the data
// func (v *CustomInterfaceSchema) validate(ctx *p.SchemaCtx) {
// defer ctx.Free()
// canCatch := v.catch != nil

// // 4. postTransforms
// defer func() {
// // only run posttransforms on success
// if !ctx.HasErrored() {
// for _, fn := range v.postTransforms {
// err := fn(ctx.Val, ctx)
// if err != nil {
// ctx.AddIssue(ctx.IssueFromUnknownError(err))
// return
// }
// }
// }
// }()

// // 1. preTransforms
// for _, fn := range v.preTransforms {
// nVal, err := fn(ctx.Val, ctx)
// // bail if error in preTransform
// if err != nil {
// if canCatch {
// v.definition.SetValue(ctx.Val, v.catch)
// return
// }
// ctx.AddIssue(ctx.IssueFromUnknownError(err))
// return
// }
// v.definition.SetValue(ctx.Val, nVal)
// }

// // 2. cast data to string & handle default/required
// // Warning. This uses generic IsZeroValue because for Validate we treat zero values as invalid for required fields. This is different from Parse.
// isZeroVal := p.IsZeroValue(ctx.Val)

// if isZeroVal {
// if v.defaultVal != nil {
// v.definition.SetValue(ctx.Val, v.defaultVal)
// } else if v.required == nil {
// // This handles optional case
// return
// } else {
// // is required & zero value
// // required
// if v.catch != nil {
// v.definition.SetValue(ctx.Val, v.catch)
// return
// } else {
// ctx.AddIssue(ctx.IssueFromTest(v.required, ctx.Val))
// return
// }
// }
// }
// // 3. tests
// for _, test := range v.tests {
// if !test.ValidateFunc(ctx.Val, ctx) {
// // catching the first error if catch is set
// if canCatch {
// v.definition.SetValue(ctx.Val, v.catch)
// return
// }
// ctx.AddIssue(ctx.IssueFromTest(&test, ctx.Val))
// }
// }

// }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Ensure code alignment with future usage and maintain consistency.

The entire parse/validate logic is currently commented out as well. If you intend to proceed with a CustomInterfaceSchema, confirm the approach is consistent with your other schemas (e.g., BoolSchema and StringSchema). For instance, you may need to confirm:

  • How data transformations and tests will integrate with the rest of the codebase.
  • Whether the fallback (catch) and default values are coherent with other schema patterns.
  • That you have adequate unit tests to guarantee reliable field parsing.

If this logic is truly experimental, consider placing it in a branch or feature flag to prevent confusion in production code.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 16, 2025

Deploying zog with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4d140f4
Status: ✅  Deploy successful!
Preview URL: https://331614a5.zog-3a0.pages.dev
Branch Preview URL: https://feat-custom-types.zog-3a0.pages.dev

View logs

@Oudwins Oudwins merged commit 29cb24d into master Mar 16, 2025
8 checks passed
@Oudwins Oudwins deleted the feat/custom-types branch March 16, 2025 13:30
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (6)
docs/docs/custom-schemas.md (6)

11-11: Grammar Improvement: Missing Comma After "Currently"
Consider adding a comma right after "Currently" to improve readability.

-Currently Zog plans to support three different ways...
+Currently, Zog plans to support three different ways...

17-20: Section Introduction: Tone Adjustment
The phrase "This is quite simple" could be simplified to "This is simple" to avoid an over-used intensifier.

🧰 Tools
🪛 LanguageTool

[style] ~19-~19: As an alternative to the over-used intensifier ‘quite’, consider replacing this phrase.
Context: ...om Schemas for Primitive Types This is quite simple to do for the supported primitive types...

(EN_WEAK_ADJECTIVE)


21-41: Formatting: Replace Hard Tabs with Spaces
Static analysis indicates that hard tabs are used in the Go code examples. Replacing these with spaces will improve markdown consistency and adhere to common style guidelines.

Also applies to: 45-66


43-44: Sentence Structure: Insert Comma Before "and"
In the sentence introducing the Coercer example, a comma before "and" will help separate the independent clauses for better clarity.

-Here is what I would recommend and it is also very similar to the way Zog creates the schemas you use:
+Here is what I would recommend, and it is also very similar to the way Zog creates the schemas you use:
🧰 Tools
🪛 LanguageTool

[uncategorized] ~43-~43: Use a comma before ‘and’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...function. Here is what I would recommend and it is also very similar to the way Zog ...

(COMMA_COMPOUND_SENTENCE)


45-66: Code Example (Coercer Function): Variable Declaration and Go Idioms
The example is informative; however, note that the variable ops is used without an explicit declaration. For clarity and to follow Go conventions, consider declaring it (e.g., using ops := append(...)).

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

48-48: Hard tabs
Column: 1

(MD010, no-hard-tabs)


49-49: Hard tabs
Column: 1

(MD010, no-hard-tabs)


50-50: Hard tabs
Column: 1

(MD010, no-hard-tabs)


51-51: Hard tabs
Column: 1

(MD010, no-hard-tabs)


52-52: Hard tabs
Column: 1

(MD010, no-hard-tabs)


53-53: Hard tabs
Column: 1

(MD010, no-hard-tabs)


54-54: Hard tabs
Column: 1

(MD010, no-hard-tabs)


55-55: Hard tabs
Column: 1

(MD010, no-hard-tabs)


56-56: Hard tabs
Column: 1

(MD010, no-hard-tabs)


57-57: Hard tabs
Column: 1

(MD010, no-hard-tabs)


58-58: Hard tabs
Column: 1

(MD010, no-hard-tabs)


59-59: Hard tabs
Column: 1

(MD010, no-hard-tabs)


60-60: Hard tabs
Column: 1

(MD010, no-hard-tabs)


61-61: Hard tabs
Column: 1

(MD010, no-hard-tabs)


62-62: Hard tabs
Column: 1

(MD010, no-hard-tabs)


63-63: Hard tabs
Column: 1

(MD010, no-hard-tabs)


68-70: Grammar Improvement: Plural Agreement and Possessive Correction
In the closing note, update "this types of schemas" to "these types of schemas" and change "schema's" to "schemas" to correct grammatical errors.

-... an API that would allow you to define this types of schemas in a more concise way (and we may still do so), to keep code consistency & reusability we recommend that you make a factory function like the one above for your custom types. And we felt that providing a simpler API could lead to people just inlining the schema's which would make it impossible to reuse them.
+... an API that would allow you to define these types of schemas in a more concise way (and we may still do so), to keep code consistency & reusability we recommend that you make a factory function like the one above for your custom types. And we felt that providing a simpler API could lead to people just inlining the schemas which would make it impossible to reuse them.
🧰 Tools
🪛 LanguageTool

[grammar] ~69-~69: The singular determiner ‘this’ does not agree with the plural noun ‘types’. Did you mean to write ‘these’?
Context: ...g an API that would allow you to define this types of schemas in a more concise way ...

(THIS_PLURAL_OF)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94f9e37 and 4d140f4.

📒 Files selected for processing (6)
  • docs/docs/configuration.md (1 hunks)
  • docs/docs/context.mdx (1 hunks)
  • docs/docs/custom-schemas.md (1 hunks)
  • docs/docs/errors.md (1 hunks)
  • docs/docs/performance.md (1 hunks)
  • docs/docs/zog-schemas.md (2 hunks)
✅ Files skipped from review due to trivial changes (4)
  • docs/docs/configuration.md
  • docs/docs/performance.md
  • docs/docs/context.mdx
  • docs/docs/errors.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/docs/zog-schemas.md
🧰 Additional context used
🪛 LanguageTool
docs/docs/custom-schemas.md

[uncategorized] ~10-~10: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...omy-of-schema) page before continuing. Currently Zog plans to support three different wa...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)


[style] ~19-~19: As an alternative to the over-used intensifier ‘quite’, consider replacing this phrase.
Context: ...om Schemas for Primitive Types This is quite simple to do for the supported primitive types...

(EN_WEAK_ADJECTIVE)


[uncategorized] ~43-~43: Use a comma before ‘and’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...function. Here is what I would recommend and it is also very similar to the way Zog ...

(COMMA_COMPOUND_SENTENCE)


[grammar] ~69-~69: The singular determiner ‘this’ does not agree with the plural noun ‘types’. Did you mean to write ‘these’?
Context: ...g an API that would allow you to define this types of schemas in a more concise way ...

(THIS_PLURAL_OF)

🪛 markdownlint-cli2 (0.17.2)
docs/docs/custom-schemas.md

48-48: Hard tabs
Column: 1

(MD010, no-hard-tabs)


49-49: Hard tabs
Column: 1

(MD010, no-hard-tabs)


50-50: Hard tabs
Column: 1

(MD010, no-hard-tabs)


51-51: Hard tabs
Column: 1

(MD010, no-hard-tabs)


52-52: Hard tabs
Column: 1

(MD010, no-hard-tabs)


53-53: Hard tabs
Column: 1

(MD010, no-hard-tabs)


54-54: Hard tabs
Column: 1

(MD010, no-hard-tabs)


55-55: Hard tabs
Column: 1

(MD010, no-hard-tabs)


56-56: Hard tabs
Column: 1

(MD010, no-hard-tabs)


57-57: Hard tabs
Column: 1

(MD010, no-hard-tabs)


58-58: Hard tabs
Column: 1

(MD010, no-hard-tabs)


59-59: Hard tabs
Column: 1

(MD010, no-hard-tabs)


60-60: Hard tabs
Column: 1

(MD010, no-hard-tabs)


61-61: Hard tabs
Column: 1

(MD010, no-hard-tabs)


62-62: Hard tabs
Column: 1

(MD010, no-hard-tabs)


63-63: Hard tabs
Column: 1

(MD010, no-hard-tabs)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (3)
docs/docs/custom-schemas.md (3)

1-6: Front Matter Block: Format and Consistency
The YAML front matter appears correctly formatted with appropriate configuration for sidebar position and table of contents levels.


7-10: Header and Introductory Note: Readability
The header and the note urging readers to visit the "[Anatomy of a Schema]" page are clear and engaging.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~10-~10: A comma may be missing after the conjunctive/linking adverb ‘Currently’.
Context: ...omy-of-schema) page before continuing. Currently Zog plans to support three different wa...

(SENT_START_CONJUNCTIVE_LINKING_ADVERB_COMMA)


13-16: List of Methods: Clarity
The three methods for creating custom schemas are clearly listed. No changes required.

Comment on lines +21 to +41
```go
// definition in your code
type Env string
const (
Prod Env = "prod".
Dev Env = "env"
)
func EnvSchema() *StringSchema[Env] {
s := &z.StringSchema[Env]
return s.OneOf([]Env{Prod, Dev}) // you can also just return the schema and define the tests when calling it it doesn't matter
}
// usage
type S struct {
Environment Env
}
schema := z.Struct(
z.Schema{
"Environment": EnvSchema() // All string methods will now be typed to Env type
}
)
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Code Example (Primitive Types): Go Syntax and Consistency

  • In line 25, the constant declaration uses an extraneous period ("prod".). It is recommended to remove the period.
  • In line 29, the instantiation s := &z.StringSchema[Env] may be more idiomatically written as s := &z.StringSchema[Env]{} to clearly initialize a new instance.
-  Prod Env = "prod".
+  Prod Env = "prod"

- s := &z.StringSchema[Env]
+ s := &z.StringSchema[Env]{}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```go
// definition in your code
type Env string
const (
Prod Env = "prod".
Dev Env = "env"
)
func EnvSchema() *StringSchema[Env] {
s := &z.StringSchema[Env]
return s.OneOf([]Env{Prod, Dev}) // you can also just return the schema and define the tests when calling it it doesn't matter
}
// usage
type S struct {
Environment Env
}
schema := z.Struct(
z.Schema{
"Environment": EnvSchema() // All string methods will now be typed to Env type
}
)
```

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