├── .codebeatignore ├── .codecov.yml ├── Tests ├── LinuxMain.swift └── ErrorExtendedTests │ └── AbortExtendedTests.swift ├── .gitignore ├── Package.swift ├── .swiftlint.yml ├── LICENSE ├── .circleci └── config.yml ├── Sources └── AbortExtended.swift └── README.md /.codebeatignore: -------------------------------------------------------------------------------- 1 | Public/** 2 | Resources/Assets/** 3 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | range: "0...100" 3 | ignore: 4 | - "Tests" 5 | -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import ErrorExtendedTests 3 | 4 | XCTMain([ 5 | testCase(AbortExtendedTests.allTests), 6 | ]) 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Packages 2 | .build 3 | .idea 4 | xcuserdata 5 | *.xcodeproj 6 | Config/secrets/ 7 | .DS_Store 8 | node_modules/ 9 | bower_components/ 10 | .swift-version 11 | CMakeLists.txt -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | import PackageDescription 2 | 3 | let package = Package( 4 | name: "ErrorExtended", 5 | dependencies: [ 6 | .Package(url: "https://github.com/vapor/vapor.git", majorVersion: 2), 7 | ] 8 | ) 9 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | included: 2 | - Sources 3 | function_body_length: 4 | warning: 60 5 | variable_name: 6 | min_length: 7 | warning: 2 8 | line_length: 80 9 | disabled_rules: 10 | - opening_brace 11 | colon: 12 | flexible_right_spacing: true 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2018 Nodes 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Tests/ErrorExtendedTests/AbortExtendedTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import ErrorExtended 3 | import Vapor 4 | import HTTP 5 | 6 | class AbortExtendedTests: XCTestCase { 7 | 8 | static var allTests : [(String, (AbortExtendedTests) -> () throws -> Void)] { 9 | return [ 10 | ("testDefaultValues", testDefaultValues), 11 | ("testCustomValues", testCustomValues) 12 | ] 13 | } 14 | 15 | 16 | // MARK: - Initialization. 17 | 18 | func testDefaultValues() { 19 | let error = AbortExtended.custom() 20 | XCTAssertEqual(error.status, .internalServerError, "Default status is wrong.") 21 | XCTAssertEqual(error.code, 0, "Default code is wrong.") 22 | XCTAssertEqual(error.reason, Status.internalServerError.reasonPhrase, "Default message is wrong") 23 | XCTAssertEqual(error.metadata, Node(["report": true]), "Default metadata is wrong") 24 | } 25 | 26 | func testCustomValues() { 27 | let error = AbortExtended.custom( 28 | status: .badGateway, 29 | code: 1337, 30 | metadata: Node(["key": "value"]), 31 | reason: "My custom error message", 32 | report: false 33 | ) 34 | XCTAssertEqual(error.status, .badGateway, "Default status is wrong.") 35 | XCTAssertEqual(error.code, 1337, "Default code is wrong.") 36 | XCTAssertEqual(error.reason, "My custom error message", "Default message is wrong") 37 | XCTAssertEqual(error.metadata, Node(["key": "value", "report": false]), "Default metadata is wrong") 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | MacOS: 4 | macos: 5 | xcode: "9.0" 6 | steps: 7 | - checkout 8 | - restore_cache: 9 | keys: 10 | - v1-spm-deps-{{ checksum "Package.swift" }} 11 | - run: 12 | name: Install CMySQL and CTLS 13 | command: | 14 | brew tap vapor/homebrew-tap 15 | brew install cmysql 16 | brew install ctls 17 | - run: 18 | name: Build and Run Tests 19 | no_output_timeout: 1800 20 | command: | 21 | swift package generate-xcodeproj --enable-code-coverage 22 | xcodebuild -scheme ErrorExtended-Package -enableCodeCoverage YES test | xcpretty 23 | - run: 24 | name: Report coverage to Codecov 25 | command: | 26 | bash <(curl -s https://codecov.io/bash) 27 | - save_cache: 28 | key: v1-spm-deps-{{ checksum "Package.swift" }} 29 | paths: 30 | - .build 31 | Linux: 32 | docker: 33 | - image: brettrtoomey/vapor-ci:0.0.1 34 | steps: 35 | - checkout 36 | - restore_cache: 37 | keys: 38 | - v2-spm-deps-{{ checksum "Package.swift" }} 39 | - run: 40 | name: Copy Package file 41 | command: cp Package.swift res 42 | - run: 43 | name: Build and Run Tests 44 | no_output_timeout: 1800 45 | command: | 46 | swift test -Xswiftc -DNOJSON 47 | - run: 48 | name: Restoring Package file 49 | command: mv res Package.swift 50 | - save_cache: 51 | key: v2-spm-deps-{{ checksum "Package.swift" }} 52 | paths: 53 | - .build 54 | workflows: 55 | version: 2 56 | build-and-test: 57 | jobs: 58 | - MacOS 59 | - Linux 60 | experimental: 61 | notify: 62 | branches: 63 | only: 64 | - master 65 | - develop 66 | -------------------------------------------------------------------------------- /Sources/AbortExtended.swift: -------------------------------------------------------------------------------- 1 | import Vapor 2 | import HTTP 3 | 4 | /// Customized error type. 5 | public struct AbortExtended: AbortError { 6 | public let status: Status 7 | public let code: Int 8 | public let metadata: Node? 9 | public let reason: String 10 | 11 | /// Creates a customized error with the given values. 12 | /// 13 | /// - Parameters: 14 | /// - status: The HTTP status code to return. 15 | /// Defaults to `Status.internalServerError`. 16 | /// - code: An integer representation of the error. 17 | /// Defaults to 0. 18 | /// - message: Textual representation on the error. 19 | /// Defaults to `Status.internalServerError.reasonPhrase`. 20 | /// - metadata: Custom metadata. Defaults to `nil`. 21 | /// - report: Indicates if middleware(s) should report this error. 22 | /// Defaults to `true`. 23 | /// This will set `metadata["report"]`. 24 | /// - Returns: Customized error (conforming to `AbortError`). 25 | public static func custom( 26 | status: Status = .internalServerError, 27 | code: Int = 0, 28 | metadata: Node? = nil, 29 | reason: String = Status.internalServerError.reasonPhrase, 30 | report: Bool = true 31 | ) -> AbortExtended { 32 | return AbortExtended( 33 | status: status, 34 | code: code, 35 | metadata: AbortExtended.resolveMetadata(metadata, report: report), 36 | reason: reason 37 | ) 38 | } 39 | 40 | /// Helper to resolve metadata. 41 | /// 42 | /// - Parameters: 43 | /// - metadata: The current metadata. 44 | /// - report: Indicates if middleware(s) should report this error. 45 | /// - Returns: Resolved metadata. 46 | private static func resolveMetadata(_ metadata: Node?, report: Bool) -> Node { 47 | var metadata = metadata ?? Node([:]) 48 | metadata["report"] = Node(report) 49 | return metadata 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ErrorExtended 2 | [![Swift Version](https://img.shields.io/badge/Swift-3-brightgreen.svg)](http://swift.org) 3 | [![Vapor Version](https://img.shields.io/badge/Vapor-2-F6CBCA.svg)](http://vapor.codes) 4 | [![Circle CI](https://circleci.com/gh/nodes-vapor/error-extended/tree/master.svg?style=shield)](https://circleci.com/gh/nodes-vapor/error-extended) 5 | [![codebeat badge](https://codebeat.co/badges/d1707d31-ba2c-4a58-b943-344d61511f34)](https://codebeat.co/projects/github-com-nodes-vapor-error-extended-master) 6 | [![codecov](https://codecov.io/gh/nodes-vapor/error-extended/branch/master/graph/badge.svg)](https://codecov.io/gh/nodes-vapor/error-extended) 7 | [![Readme Score](http://readme-score-api.herokuapp.com/score.svg?url=https://github.com/nodes-vapor/error-extended)](http://clayallsopp.github.io/readme-score?url=https://github.com/nodes-vapor/error-extended) 8 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/nodes-vapor/error-extended/master/LICENSE) 9 | 10 | Vapor errors with more granularity. 11 | 12 | 13 | ## 📦 Installation 14 | 15 | Update your `Package.swift` file. 16 | ```swift 17 | .Package(url: "https://github.com/nodes-vapor/error-extended.git", majorVersion: 1) 18 | ``` 19 | 20 | 21 | ## Getting started 🚀 22 | 23 | ```swift 24 | import ErrorExtended 25 | ``` 26 | 27 | If you need more granular control on the content that goes into your errors conforming to the `AbortError` protocol you can use the `AbortExtended` type instead (which conforms to `AbortError`). This type will give you access to all of the parameters as well as providing you with some convenient extra parameters. 28 | 29 | A couple of examples: 30 | 31 | ```swift 32 | throw AbortExtended.custom(code: 1337) 33 | ``` 34 | 35 | ```swift 36 | throw AbortExtended.custom( 37 | status: .badRequest, 38 | code: 1337, 39 | message: "Sorry, bad request", 40 | report: false 41 | ) 42 | ``` 43 | 44 | ```swift 45 | throw AbortExtended.custom( 46 | status: .badGateway, 47 | code: Status.badGateway.statusCode, 48 | message: Status.badGateway.reasonPhrase, 49 | metadata: Node(["key": "value"]), 50 | report: false 51 | ) 52 | ``` 53 | 54 | Any middleware (e.g. [bugsnag](https://github.com/nodes-vapor/bugsnag)) that tries to catch errors conforming to `AbortError` will then pick this up. 55 | 56 | 57 | ## 🏆 Credits 58 | 59 | This package is developed and maintained by the Vapor team at [Nodes](https://www.nodes.dk). 60 | The package owner for this project is [Rasmus](https://github.com/rasmusebbesen). 61 | 62 | ## 📄 License 63 | 64 | This package is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT) 65 | --------------------------------------------------------------------------------