{"id":15038371,"url":"https://github.com/heitorgcosta/quiver","last_synced_at":"2025-06-12T06:42:42.060Z","repository":{"id":62451734,"uuid":"104758946","full_name":"heitorgcosta/Quiver","owner":"heitorgcosta","description":"Validation, searching and filtering made easy for swift.","archived":false,"fork":false,"pushed_at":"2019-10-07T21:46:49.000Z","size":68,"stargazers_count":27,"open_issues_count":2,"forks_count":3,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-08T13:51:37.821Z","etag":null,"topics":["carthage","cocoapods","filtering","searching","swift","swift-4","swift4","validation","xcode","xcode9"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/heitorgcosta.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-25T14:15:11.000Z","updated_at":"2019-07-31T11:50:32.000Z","dependencies_parsed_at":"2022-11-01T23:45:32.122Z","dependency_job_id":null,"html_url":"https://github.com/heitorgcosta/Quiver","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heitorgcosta%2FQuiver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heitorgcosta%2FQuiver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heitorgcosta%2FQuiver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heitorgcosta%2FQuiver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/heitorgcosta","download_url":"https://codeload.github.com/heitorgcosta/Quiver/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248131466,"owners_count":21052819,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["carthage","cocoapods","filtering","searching","swift","swift-4","swift4","validation","xcode","xcode9"],"created_at":"2024-09-24T20:38:12.988Z","updated_at":"2025-04-09T23:40:34.691Z","avatar_url":"https://github.com/heitorgcosta.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Quiver\n\n[![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://opensource.org/licenses/MIT)\n![Swift 5](https://img.shields.io/badge/Swift-5.0-green.svg?style=flat)\n![Xcode 10.2](https://img.shields.io/badge/Xcode-10.2-yellow.svg?style=flat)\n[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Quiver.svg)](https://img.shields.io/cocoapods/v/Quiver.svg)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![Build Status](https://travis-ci.org/heitorgcosta/Quiver.svg?branch=master)](https://travis-ci.org/heitorgcosta/Quiver)\n[![codecov](https://codecov.io/gh/heitorgcosta/Quiver/branch/master/graph/badge.svg)](https://codecov.io/gh/heitorgcosta/Quiver)\n[![codebeat badge](https://codebeat.co/badges/8649319f-2189-422c-a2ab-293ac4646343)](https://codebeat.co/projects/github-com-heitorgcosta-quiver-master)\n\n\nQuiver is a library that provides an easy way to validate, search and filter objects.\n\n# Installation\n\n## Cocoapods\n```\npod 'Quiver', '~\u003e 1.2'\n```\n\n## Carthage\n```\ngithub \"heitorgcosta/Quiver\" ~\u003e 1.2  \n```\n\n# Usage\n\n## Validating\n\nObjects can be easily validated by implementing the `Validatable` protocol.\nTo do so, `validations(with:)` must be implemented. The mapping is made with the new Swift 4 smart keypaths.\n\n```swift\nstruct Person {\n    var name: String?\n    var age: Int?\n}\n\nextension Person: Validatable {\n    func validations(with mapper: ValidatorMapper) {\n        // Name is required and must be at least 4 characters long.\n        mapper[\\Person.name] = [.required(),\n                                .length(min: 4)]\n\n        // Age is required and must be 18 or over\n        mapper[\\Person.age] = [.required(),\n                               .greaterOrEqual(to: 18)]\n    }\n}\n```\n\nAny object implementing `Validatable` can call `validate()`, which returns a result object.\n\n```swift\nlet person = Person(name: \"Hector\", age: 23)\nlet result = person.validate()\n\nprint(result.success) // Prints 'true'\n```\n\nThe results also contains the errors occurred.\n\n```swift\nlet person = Person(name: \"Hector\", age: nil) \nlet result = person.validate()\n\nprint(result.success) // Prints 'false'\nprint(result.error.items.count) // Prints 1, since it does not fulfill the 'required' validation\n```\n\nAlso, each validator can contain a custom message defined by you.\n\n```swift\nextension Person: Validatable {\n    func validations(with mapper: ValidatorMapper) {\n        mapper[\\Person.name] = [.required(message: \"The name is required\"),\n                                .length(min: 4, message: \"The name should be at least 4 characters long\")]\n\n        mapper[\\Person.age] = [.required(message: \"The age is required\"),\n                               .greaterOrEqual(to: 18, message: \"The age should be 18 or over\")]\n    }\n}\n\nlet person = Person(name: \"Heitor\", age: 17)\nlet result = person.validate()\n\nprint(result.error.firstItem?.message ?? \"No errors found\") // Will print 'The age should be 18 or over'\n```\n\nValidators are still in the beginning and more will be added in the future.\n\n## Searching\n\nFirst, objects to be searched must implement the `Searchable` protocol. The `searchableFields()` function should return all searchable properties.\n\n```swift\nstruct Person {\n    var name: String\n    var age: Int\n}\n\nextension Person: Searchable {\n    func searchableFields() -\u003e [Any?] {\n        return [name, age]\n    }\n}\n```\n\nThen, any array of this object can use the `search()` function to get an array with the matching results.\n\n```swift\n// If any searchable field of a person contains \"John\", it is returned in the result array.\n\nlet results = personsArray.search(with: \"John\") // Search is not case sensitive by default.\nlet caseSensitiveResults = personsArray.search(with: \"John\", caseSensitive: true) // Explicit case sensitivity\n```\n\n## Filtering\n\nAn array of objects can be filtered using the validators included in this library using the `filter(by:with:)`, using a keypath and an array of validators.\n\n```swift\nlet persons: [Person] = [] // Just imagine a great collection of persons\nlet filtered = persons.filter(by: \\Person.name, with: [.length(min: 4)]) // Filter persons that contains name with length of at least 4 characters\n```\n\n# License \n\nQuiver is released under the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheitorgcosta%2Fquiver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fheitorgcosta%2Fquiver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheitorgcosta%2Fquiver/lists"}