Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
twof committed Sep 29, 2018
0 parents commit 27f9ca6
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
178 changes: 178 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
{
"object": {
"pins": [
{
"package": "Console",
"repositoryURL": "https://github.com/vapor/console.git",
"state": {
"branch": null,
"revision": "5b9796d39f201b3dd06800437abd9d774a455e57",
"version": "3.0.2"
}
},
{
"package": "Core",
"repositoryURL": "https://github.com/vapor/core.git",
"state": {
"branch": null,
"revision": "eb876a758733166a4fb20f3f0a17b480c5ea563e",
"version": "3.4.3"
}
},
{
"package": "Crypto",
"repositoryURL": "https://github.com/vapor/crypto.git",
"state": {
"branch": null,
"revision": "5605334590affd4785a5839806b4504407e054ac",
"version": "3.3.0"
}
},
{
"package": "DatabaseKit",
"repositoryURL": "https://github.com/vapor/database-kit.git",
"state": {
"branch": null,
"revision": "3a17dbbe9be5f8c37703e4b7982c1332ad6b00c4",
"version": "1.3.1"
}
},
{
"package": "Fluent",
"repositoryURL": "https://github.com/vapor/fluent.git",
"state": {
"branch": null,
"revision": "270b6fa372f03809b9795e8f8b9d1c31267a0ff3",
"version": "3.0.0"
}
},
{
"package": "HTTP",
"repositoryURL": "https://github.com/vapor/http.git",
"state": {
"branch": null,
"revision": "9e3eff9dfa4df7fc282bf27f801c72b3ffbfd984",
"version": "3.1.4"
}
},
{
"package": "Multipart",
"repositoryURL": "https://github.com/vapor/multipart.git",
"state": {
"branch": null,
"revision": "e57007c23a52b68e44ebdfc70cbe882a7c4f1ec3",
"version": "3.0.2"
}
},
{
"package": "Routing",
"repositoryURL": "https://github.com/vapor/routing.git",
"state": {
"branch": null,
"revision": "3219e328491b0853b8554c5a694add344d2c6cfb",
"version": "3.0.1"
}
},
{
"package": "Service",
"repositoryURL": "https://github.com/vapor/service.git",
"state": {
"branch": null,
"revision": "281a70b69783891900be31a9e70051b6fe19e146",
"version": "1.0.0"
}
},
{
"package": "SQL",
"repositoryURL": "https://github.com/vapor/sql.git",
"state": {
"branch": null,
"revision": "a35cf1dced4ddd32bb2dc8b6e765aea7bcf8d6e0",
"version": "2.1.0"
}
},
{
"package": "swift-nio",
"repositoryURL": "https://github.com/apple/swift-nio.git",
"state": {
"branch": null,
"revision": "5d8148c8b45dfb449276557f22120694567dd1d2",
"version": "1.9.5"
}
},
{
"package": "swift-nio-ssl",
"repositoryURL": "https://github.com/apple/swift-nio-ssl.git",
"state": {
"branch": null,
"revision": "8380fa29a2af784b067d8ee01c956626ca29f172",
"version": "1.3.1"
}
},
{
"package": "swift-nio-ssl-support",
"repositoryURL": "https://github.com/apple/swift-nio-ssl-support.git",
"state": {
"branch": null,
"revision": "c02eec4e0e6d351cd092938cf44195a8e669f555",
"version": "1.0.0"
}
},
{
"package": "swift-nio-zlib-support",
"repositoryURL": "https://github.com/apple/swift-nio-zlib-support.git",
"state": {
"branch": null,
"revision": "37760e9a52030bb9011972c5213c3350fa9d41fd",
"version": "1.0.0"
}
},
{
"package": "TemplateKit",
"repositoryURL": "https://github.com/vapor/template-kit.git",
"state": {
"branch": null,
"revision": "db35b1c35aabd0f5db3abca0cfda7becfe9c43e2",
"version": "1.1.0"
}
},
{
"package": "URLEncodedForm",
"repositoryURL": "https://github.com/vapor/url-encoded-form.git",
"state": {
"branch": null,
"revision": "932024f363ee5ff59059cf7d67194a1c271d3d0c",
"version": "1.0.5"
}
},
{
"package": "Validation",
"repositoryURL": "https://github.com/vapor/validation.git",
"state": {
"branch": null,
"revision": "156f8adeac3440e868da3757777884efbc6ec0cc",
"version": "2.1.0"
}
},
{
"package": "Vapor",
"repositoryURL": "https://github.com/vapor/vapor.git",
"state": {
"branch": null,
"revision": "157d3b15336caa882662cc75024dd04b2e225246",
"version": "3.1.0"
}
},
{
"package": "WebSocket",
"repositoryURL": "https://github.com/vapor/websocket.git",
"state": {
"branch": null,
"revision": "149af03348f60ac8b84defdf277112d62fd8c704",
"version": "1.0.2"
}
}
]
},
"version": 1
}
33 changes: 33 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// swift-tools-version:4.2
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "CrudRouter",
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "CrudRouter",
targets: ["CrudRouter"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
// 💧 A server-side Swift web framework.
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),

// 🔵 Swift ORM (queries, models, relations, etc) built on SQLite 3.
.package(url: "https://github.com/vapor/fluent.git", from: "3.0.0")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "CrudRouter",
dependencies: ["Fluent", "Vapor"]),
.testTarget(
name: "CrudRouterTests",
dependencies: ["CrudRouter"]),
]
)
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# CrudRouter

A description of this package.
74 changes: 74 additions & 0 deletions Sources/CrudRouter/CrudRouter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import Vapor
import Fluent

public protocol CrudControllerProtocol {
associatedtype ModelType: Model, Content where ModelType.ID: Parameter
func indexAll(_ req: Request) throws -> Future<[ModelType]>
func index(_ req: Request) throws -> Future<ModelType>
func update(_ req: Request) throws -> Future<ModelType>
func create(_ req: Request) throws -> Future<ModelType>
func delete(_ req: Request) throws -> Future<HTTPStatus>
}

public extension CrudControllerProtocol {
func indexAll(_ req: Request) throws -> Future<[ModelType]> {
return ModelType.query(on: req).all().map { Array($0) }
}

func index(_ req: Request) throws -> Future<ModelType> {
let id: ModelType.ID = try getId(from: req)
return ModelType.find(id, on: req).unwrap(or: Abort(.notFound))
}

func create(_ req: Request) throws -> Future<ModelType> {
return try req.content.decode(ModelType.self).flatMap { model in
return model.save(on: req)
}
}

func update(_ req: Request) throws -> Future<ModelType> {
let id: ModelType.ID = try getId(from: req)
return try req.content.decode(ModelType.self).flatMap { model in
var temp = model
temp.fluentID = id
return temp.update(on: req)
}
}

func delete(_ req: Request) throws -> Future<HTTPStatus> {
let id: ModelType.ID = try getId(from: req)
return ModelType
.find(id, on: req)
.unwrap(or: Abort(.notFound))
.flatMap { model in
return model.delete(on: req).transform(to: HTTPStatus.ok)
}
}
}

fileprivate extension CrudControllerProtocol {
func getId<T: ID>(from req: Request) throws -> T {
guard let id = try req.parameters.next(ModelType.ID.self) as? T else { fatalError() }

return id
}
}

fileprivate final class CrudController<T: Model>: CrudControllerProtocol where T.ID: Parameter, T: Content {
typealias ModelType = T
}

public extension Router {
func crudRegister<ModelType: Model & Content>(
_ path: PathComponentsRepresentable...,
for type: ModelType.Type
) where ModelType.ID: Parameter {
let controller = CrudController<ModelType>()

self.get(path, CrudController<ModelType>.ModelType.ID.parameter, use: controller.index)
self.get(path, use: controller.indexAll)
self.post(path, use: controller.create)
self.put(path, CrudController<ModelType>.ModelType.ID.parameter, use: controller.update)
self.delete(path, CrudController<ModelType>.ModelType.ID.parameter, use: controller.delete)
}
}
15 changes: 15 additions & 0 deletions Tests/CrudRouterTests/CrudRouterTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import XCTest
@testable import CrudRouter

final class CrudRouterTests: XCTestCase {
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct
// results.
XCTAssertEqual(CrudRouter().text, "Hello, World!")
}

static var allTests = [
("testExample", testExample),
]
}
9 changes: 9 additions & 0 deletions Tests/CrudRouterTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import XCTest

#if !os(macOS)
public func allTests() -> [XCTestCaseEntry] {
return [
testCase(CrudRouterTests.allTests),
]
}
#endif
7 changes: 7 additions & 0 deletions Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import XCTest

import CrudRouterTests

var tests = [XCTestCaseEntry]()
tests += CrudRouterTests.allTests()
XCTMain(tests)

0 comments on commit 27f9ca6

Please sign in to comment.