{"id":13871855,"url":"https://github.com/mczachurski/Swiftgger","last_synced_at":"2025-07-16T01:31:52.547Z","repository":{"id":49579389,"uuid":"126718298","full_name":"mczachurski/Swiftgger","owner":"mczachurski","description":"OpenAPI support for server side Swift projects.","archived":false,"fork":false,"pushed_at":"2021-06-26T08:14:36.000Z","size":762,"stargazers_count":109,"open_issues_count":3,"forks_count":13,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-11-15T18:12:11.632Z","etag":null,"topics":["openapi","swagger","swagger-ui","swift"],"latest_commit_sha":null,"homepage":null,"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/mczachurski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-25T16:44:41.000Z","updated_at":"2024-02-10T11:27:37.000Z","dependencies_parsed_at":"2022-09-14T15:52:18.831Z","dependency_job_id":null,"html_url":"https://github.com/mczachurski/Swiftgger","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mczachurski%2FSwiftgger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mczachurski%2FSwiftgger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mczachurski%2FSwiftgger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mczachurski%2FSwiftgger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mczachurski","download_url":"https://codeload.github.com/mczachurski/Swiftgger/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226089951,"owners_count":17572112,"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":["openapi","swagger","swagger-ui","swift"],"created_at":"2024-08-05T23:00:28.304Z","updated_at":"2024-11-23T19:31:19.674Z","avatar_url":"https://github.com/mczachurski.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"# Swiftgger\n\n![Build Status](https://github.com/mczachurski/Swiftgger/workflows/Build/badge.svg)\n[![Swift 5.3](https://img.shields.io/badge/Swift-5.3-orange.svg?style=flat)](ttps://developer.apple.com/swift/)\n[![Swift Package Manager](https://img.shields.io/badge/SPM-compatible-4BC51D.svg?style=flat)](https://swift.org/package-manager/)\n[![Platforms macOS | Linux](https://img.shields.io/badge/Platforms-macOS%20%7C%20Linux%20-lightgray.svg?style=flat)](https://developer.apple.com/swift/)\n\nSwiftgger is a Swift library which can generate output compatible with [OpenAPI version 3.0.1](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md). You can describe your API using Swiftgger classes and expose OpenAPI definition by endpoint in your API. URL to that endpoint can be used in [Swagger UI](https://swagger.io/swagger-ui/).\n\n![swagger](Images/screen-02.png)\n\nAlso you can user Swiftgger to generate Swift files based on OpenAPI definition file. Example usage:\n\n```swift\n$ swiftgger-generator -u http://localhost:8000/openapi.json -o ../output\n```\n\nAbove command will generate Swift files with model classes and HTTP client services.\n\n\u003e This feature is under development now.\n\n## Getting started\n\nSwiftgger support Swift Package Manager. You have to add to your `Package.swift` file information about Swiftgger. Below is a simple example.\n\n```swift\nlet package = Package(\n    name: \"YourApp\",\n    dependencies: [\n        .package(url: \"https://github.com/mczachurski/Swiftgger.git\", from: \"1.4.0\")\n    ],\n    targets: [\n        .target(name: \"YourApp\", dependencies: [\"Swiftgger\"]),\n        .testTarget(name: \"YourAppTests\", dependencies: [\"YourApp\"])\n    ]\n)\n``` \n\n\u003e Swiftgger requires at least version 5.3 of Swift.\n\n## How to use it\n\nUnfortunately Swift is not perfect in *reflection* (introspection) and a lot of settings we have to do manually. \n\n### Basic information\n\n`OpenAPIBuilder` is main object which is responsible for collect information about our API structure and generating OpenAPI response. It contains some basic information about API like title, version, author, license etc.\n\n```swift\nlet openAPIBuilder = OpenAPIBuilder(\n    title: \"Tasker server API\",\n    version: \"1.0.0\",\n    description: \"This is a sample server for task server application.\",\n    termsOfService: \"http://example.com/terms/\",\n    contact: APIContact(name: \"John Doe\", email: \"john.doe@some-email.org\", url: URL(string: \"http://example-domain.com/@john\")),\n    license: APILicense(name: \"MIT\", url: URL(string: \"http://mit.license\")),\n    authorizations: [.jwt(description: \"You can get token from *sign-in* action from *Account* controller.\")]\n)\n```\n\nWe can use `openAPIBuilder` object if we want to specify list of controllers and actions.\n\n### Controllers (tags/groups)\n\nAdding information about controller is pretty simple. We have to execute `add` method on `OpenAPIBuilder` object.\n\n```swift\nopenAPIBuilder.add(\n    APIController(name: \"Users\", description: \"Controller where we can manage users\", actions: [])\n)\n```\n\n### Actions (paths/endpoints)\n\nEach controller can have list of actions (routes) with name, description, response and requests information.\n\n**Get by id action (object in response)**\n\n```swift\nAPIAction(method: .get, route: \"/users/{id}\",\n    summary: \"Getting user by id\",\n    description: \"Action for getting specific user from server\",\n    parameters: [\n        APIParameter(name: \"id\", description: \"User id\", required: true)\n    ],\n    responses: [\n        APIResponse(code: \"200\", description: \"Specific user\", type: .object(UserDto.self),\n        APIResponse(code: \"404\", description: \"User with entered id not exists\"),\n        APIResponse(code: \"401\", description: \"User not authorized\")\n    ],\n    authorization: true\n)\n```\n\n**Get action (value type in response)**\n\n```swift\nAPIAction(method: .get, route: \"/version\",\n    summary: \"Getting system version\",\n    description: \"Action for getting application current version\",\n    responses: [\n        APIResponse(code: \"200\", description: \"Specific user\", type: .value(\"1.0.0\")\n    ]\n)\n```\n\n**Post action**\n\n```swift\nAPIAction(method: .post, route: \"/users\",\n    summary: \"Adding new user\",\n    description: \"Action for adding new user to the server\",\n    request: APIRequest(type: .object(UserDto.self), description: \"Object with user information.\"),\n    responses: [\n        APIResponse(code: \"200\", description: \"User data after adding to the system\", type: .object(UserDto.self)),\n        APIResponse(code: \"400\", description: \"There was issues during adding new user\", type: .object(ValidationErrorResponseDto.self)),\n        APIResponse(code: \"401\", description: \"User not authorized\")\n    ],\n    authorization: true\n)\n```\n\n### Objects schemas\n\nBesides controllers and actions we have to specify list of objects which can be used in API. We can do this like on following snippet.\n\n```swift\nopenAPIBuilder.add([\n    APIObject(object: UserDto(id: UUID(), createDate: Date(), name: \"John Doe\", email: \"email@test.com\", isLocked: false)),\n    APIObject(object: ValidationErrorResponseDto(message: \"Object is invalid\", errors: [\"property\": \"Information about error.\"]))\n])\n```\n\n### Example of CRUD controller configuration\n\nBelow there is an example how to configure full CRUD operation. Of course in that example whole configuration is done in one place. However in your application you can put endpoint/actions configuration near your implementation (separate for each action).\n\n\n```swift\n\n// Create builder.\nlet openAPIBuilder = OpenAPIBuilder(\n    title: \"Tasker server API\",\n    version: \"1.0.0\",\n    description: \"This is a sample server for task server application.\",\n    authorizations: [.jwt(description: \"You can get token from *sign-in* action from *Account* controller.\")]\n)\n.add(APIController(name: \"Users\", description: \"Controller where we can manage users\", actions: [\n        APIAction(method: .get, route: \"/users\",\n            summary: \"Getting all users\",\n            description: \"Action for getting all users from server\",\n            responses: [\n                APIResponse(code: \"200\", description: \"List of users\", type: .object(UserDto.self)),\n                APIResponse(code: \"401\", description: \"User not authorized\")\n            ],\n            authorization: true\n        ),\n        APIAction(method: .get, route: \"/users/{id}\",\n            summary: \"Getting user by id\",\n            description: \"Action for getting specific user from server\",\n            parameters: [\n                APIParameter(name: \"id\", description: \"User id\", required: true)\n            ],\n            responses: [\n                APIResponse(code: \"200\", description: \"Specific user\", type: .object(UserDto.self)),\n                APIResponse(code: \"404\", description: \"User with entered id not exists\"),\n                APIResponse(code: \"401\", description: \"User not authorized\")\n            ],\n            authorization: true\n        ),\n        APIAction(method: .post, route: \"/users\",\n            summary: \"Adding new user\",\n            description: \"Action for adding new user to the server\",\n            request: APIRequest(type: .object(UserDto.self), description: \"Object with user information.\"),\n            responses: [\n                APIResponse(code: \"200\", description: \"User data after adding to the system\", type: .object(UserDto.self)),\n                APIResponse(code: \"400\", description: \"There was issues during adding new user\", type: .object(ValidationErrorResponseDto.self)),\n                APIResponse(code: \"401\", description: \"User not authorized\")\n            ],\n            authorization: true\n        ),\n        APIAction(method: .put, route: \"/users/{id}\",\n            summary: \"Updating user\",\n            description: \"Action for updating specific user in the server\",\n            parameters: [\n                APIParameter(name: \"id\", description: \"User id\", required: true)\n            ],\n            request: APIRequest(type: .object(UserDto.self), description: \"Object with user information.\"),\n            responses: [\n                APIResponse(code: \"200\", description: \"User data after adding to the system\", type: .object(UserDto.self)),\n                APIResponse(code: \"400\", description: \"There was issues during updating user\", type: .object(ValidationErrorResponseDto.self)),\n                APIResponse(code: \"404\", description: \"User with entered id not exists\"),\n                APIResponse(code: \"401\", description: \"User not authorized\")\n            ],\n            authorization: true\n        ),\n        APIAction(method: .delete, route: \"/users/{id}\",\n            summary: \"Deleting user\",\n            description: \"Action for deleting user from the database\",\n            parameters: [\n                APIParameter(name: \"id\", description: \"User id\", required: true)\n            ],\n            responses: [\n                APIResponse(code: \"200\", description: \"User was deleted\"),\n                APIResponse(code: \"404\", description: \"User with entered id not exists\"),\n                APIResponse(code: \"401\", description: \"User not authorized\")\n            ],\n            authorization: true\n        )\n    ])\n)\n.add([\n    APIObject(object: UserDto(id: UUID(), createDate: Date(), name: \"John Doe\", email: \"email@test.com\", isLocked: false)),\n    APIObject(object: ValidationErrorResponseDto(message: \"Object is invalid\", errors: [\"property\": \"Information about error.\"]))\n])\n```\n\n### Create OpenAPI objects\n\nWhen you prepared configuration for all your controllers/actions then you have to execute following code:\n\n```swift\nlet document = try openAPIBuilder.built()\n```\n\nObject `document` stores information about your API and it's compatible with OpenAPI standard. Now you have to serialize that object to JSON and expose by additional endpoint in your API application. That JSON (endpoint) can by consume by any OpenAPI compatible client applications.\n\n[Swagger UI](https://swagger.io/swagger-ui/) is great tool which visualize for example request model, parameters etc.\n\n![user in swagger 1](Images/screen-01.png)\n\nYou have also clear list of possible responses which can be returned by your endpoints.\n\n![user in swagger 2](Images/screen-03.png)\n\nMore examples you can find in my other GitHub [project](https://github.com/mczachurski/TaskServerSwift).\n\n## Demo\n\nTasker server OpenAPI JSON: [https://taskerswift.azurewebsites.net/openapi](https://taskerswift.azurewebsites.net/openapi)\n\nTasker server Swagger UI: [https://taskerswift-swagger.azurewebsites.net/](https://taskerswift-swagger.azurewebsites.net/)\n\n## Swiftgger generator\n\n`swiftgger-generator` is a simple application which can generate Swift files based on OpenAPI definition.  Application generates files for model classes and HTTP client services for each controller (group). Command line arguments:\n\n```bash\nswiftgger-generator: [command_option] [-f jsonFile] [-u url] [-o path]\")\nCommand options are:\n -h            show this message and exit\n -v            show program version and exit\n -f            input .json file with OpenAPI description\n -u            input URL which returns .json with OpenAPI description\n -o            output directory (default is 'output')\n```\n\n**TODO:**\n - [ ] Client services generation\n - [ ] Infromation how to use generated HTTP client services\n\n## License\n\nThis project is licensed under the terms of the MIT license.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmczachurski%2FSwiftgger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmczachurski%2FSwiftgger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmczachurski%2FSwiftgger/lists"}