SlideShare ist ein Scribd-Unternehmen logo
1 von 41
Downloaden Sie, um offline zu lesen
TodoList
Tutorial
Creating a TodoList
→ Creating a project
→ Add dependencies
→ Simple Routing
→ Error Handling
→ Promises
→ Testing
Create a Project
mkdir TodoList
cd TodoList
swift package init
swift package generate-xcodeproj
Add Dependencies
import PackageDescription
let package = Package(
name: "MyTodoList",
dependencies: [
.Package(url: "https://github.com/IBM-Swift/Kitura", majorVersion: 0, minor: 32),
.Package(url: "https://github.com/IBM-Swift/HeliumLogger", majorVersion: 0, minor: 17)
]
)
Simple Route
let router = Router()
router.get("/") { request, response, next in
response.status(.OK).send("Hello World!")
}
Simple Server
Kitura.addHTTPServer(onPort: 8090, with: todoListController.router)
Kitura.run()
Simple Logger
import HeliumLogger
HeliumLogger.use()
Log.info("Hello world!")
Using multiple targets
targets: [
Target(name: "Server", dependencies: [.Target(name: "TodoList")]),
Target(name: "TodoList")
],
Separation project to:
→ Sources/TodoList/TodoList.swift
→ Sources/Server/main.swift
Create a Controller
public final class TodoListController {
public let router = Router()
public init() {
router.get("/v1/tasks", handler: handleGetTasks)
router.post("/v1/tasks", handler: handlerAddTask)
}
}
Add routes
func handleGetTasks(request: RouterRequest,
response: RouterResponse,
next: @escaping () -> Void) throws {
}
func handleAddTask(request: RouterRequest,
response: RouterResponse,
next: @escaping () -> Void) throws {
}
Add basic collection to Controller
let tasks: [String] = []
Get tasks
func handleGetTasks(request: RouterRequest,
response: RouterResponse,
next: @escaping () -> Void) throws {
response.status(.OK).send(json: JSON( tasks ))
}
Add ability to add tasks
Add a Body Parser
router.all("*", middleware: BodyParser())
Simplify getting the JSON back
extension RouterRequest {
var json: JSON? {
guard let body = self.body else {
return nil
}
guard case let .json(json) = body else {
return nil
}
return json
}
}
Get the description back
func handleAddTask(request: RouterRequest,
response: RouterResponse,
next: @escaping () -> Void) throws {
if let json = request.json else {
response.status(.badRequest)
next()
return
}
let description = json["description"].stringValue
tasks.append(description)
}
Protect your array
let queue = DispatchQueue(label: "com.example.tasklist")
queue.sync {
}
Create a more rich Task
struct Task {
let id: UUID
let description: String
let createdAt: Date
let isCompleted: Bool
}
Make it Equatible
extension Task: Equatable { }
func == (lhs: Task, rhs: Task) -> Bool {
if lhs.id == rhs.id,
lhs.description == rhs.description,
lhs.createdAt == rhs.createdAt,
lhs.isCompleted == rhs.isCompleted
{
return true
}
return false
}
Make things tranformable to Dictionary
typealias StringValuePair = [String: Any]
protocol StringValuePairConvertible {
var stringValuePairs: StringValuePair {get}
}
Make collections also tranformable to Dictionary
extension Array where Element : StringValuePairConvertible {
var stringValuePairs: [StringValuePair] {
return self.map { $0.stringValuePairs }
}
}
Make Task a StringValuePairConvertible
extension Task: StringValuePairConvertible {
var stringValuePairs: StringValuePair {
return [
"id": "(self.id)",
"description": self.description,
"createdAt": self.createdAt.timeIntervalSinceReferenceDate,
"isCompleted": self.isCompleted
]
}
}
Change [String] to [Task]
private var tasks: [Task] = []
response.status(.OK).send(json: JSON(task.stringValuePairs))
Add task with Tasks
task.append(Task(id: UUID(),
description: "Do the dishes",
createdAt: Date(),
isCompleted: false))
Factor out the Database
final class TaskDatabase {
private var storage: [Task] = []
let queue = DispatchQueue(label: "com.example.tasklist")
func addTask(oncompletion: (Task) -> Void) {
queue.sync {
self.storage.append(task)
oncompletion(task)
}
}
func getTasks(oncompletion: ([Task]) -> Void) {
queue.sync {
oncompletion(self.storage)
}
}
}
Use asynchronous callbacks
Error Handling
TaskListError
enum TaskListError : LocalizedError {
case descriptionTooShort(String)
case descriptionTooLong(String)
case noJSON
Error Description
var errorDescription: String? {
switch self {
case .descriptionTooShort(let string): return "(string) is too short"
case .descriptionTooLong(let string): return "(string) is too long"
case .noJSON: return "No JSON in payload"
}
}
Make it convertible to JSON
extension TaskListError: StringValuePairConvertible {
var stringValuePairs: StringValuePair {
return ["error": self.errorDescription ?? ""]
}
}
Validating the Request
let maximumLength = 40
let minimumLength = 3
struct AddTaskRequest {
let description: String
}
Validate the request
func validateRequest(request: RouterRequest) throws -> AddTaskRequest {
guard let json = request.json else {
throw TaskListError.noJSON
}
let description = json["description"].stringValue
if description.characters.count > maximumLength {
throw TaskListError.descriptionTooLong(description)
}
if description.characters.count < minimumLength {
throw TaskListError.descriptionTooShort(description)
}
return AddTaskRequest(description: description)
}
Use Promises
Add MiniPromiseKit
.Package(url: "https://github.com/davidungar/miniPromiseKit", majorVersion: 4, minor: 1),
Create Promises
final class TaskDatabase {
private var storage: [Task] = []
let queue = DispatchQueue(label: "com.example.tasklist")
func addTask(task: Task) -> Promise<Task> {
return Promise{ fulfill, reject in
queue.sync {
self.storage.append(task)
fulfill(task)
}
}
}
func getTasks() -> Promise<[Task]> {
return Promise{ fulfill, reject in
queue.sync {
fulfill(self.storage)
}
}
}
}
Use the Promises
_ = firstly {
taskDatabase.getTasks()
}.then (on: self.queue) { tasks in
response.status(.OK).send(json: JSON(tasks.stringValuePairs))
}
.catch (on: self.queue) { error in
if let err = error as? TaskListError {
response.status(.badRequest).send(json: JSON(err.stringValuePairs))
}
}
.always(on: self.queue) {
next()
}
Use the Promises
_ = firstly { () throws -> Promise<Task> in
let addRequest = try validateRequest(request: request)
let task = Task(with: addRequest)
return taskDatabase.addTask(task: task)
}
.then (on: self.queue) { task -> Void in
response.status(.OK).send(json: JSON(task.stringValuePairs))
}
.catch (on: self.queue) { error in
if let err = error as? TaskListError {
response.status(.badRequest).send(json: JSON(err.stringValuePairs))
}
}
.always(on: self.queue) {
next()
}
Testing
Set up Kitura framework
private let queue = DispatchQueue(label: "Kitura runloop", qos: .userInitiated, attributes: .concurrent)
public let defaultSession = URLSession(configuration: .default)
private let todoListController = TodoListController()
override func setUp() {
super.setUp()
Kitura.addHTTPServer(onPort: 8090, with: todoListController.router)
queue.async {
Kitura.run()
}
}
Add a test
func testGetTodos() {
let expectation1 = expectation(description: "Get Todos")
var url: URLRequest = URLRequest(url: URL(string: "http://localhost:8090/v1/tasks")!)
url.addValue("application/json", forHTTPHeaderField: "Content-Type")
url.httpMethod = "GET"
url.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData
let dataTask = defaultSession.dataTask(with: url) {
data, response, error in
XCTAssertNil(error)
switch (response as? HTTPURLResponse)?.statusCode {
case 200?:
guard let data = data else {
XCTAssert(false)
return
}
let json = JSON(data: data)
print(json)
expectation1.fulfill()
case nil: XCTFail("response not HTTPURLResponse")
case let code?: XCTFail("bad status: (code)")
}
}
dataTask.resume()
waitForExpectations(timeout: 10, handler: { _ in })
}
Enable Code coverage
swift package generate-xcodeproj --enable-code-coverage

Weitere ähnliche Inhalte

Was ist angesagt?

The Ring programming language version 1.10 book - Part 50 of 212
The Ring programming language version 1.10 book - Part 50 of 212The Ring programming language version 1.10 book - Part 50 of 212
The Ring programming language version 1.10 book - Part 50 of 212Mahmoud Samir Fayed
 
The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 40 of 184
The Ring programming language version 1.5.3 book - Part 40 of 184The Ring programming language version 1.5.3 book - Part 40 of 184
The Ring programming language version 1.5.3 book - Part 40 of 184Mahmoud Samir Fayed
 
Scala - den smarta kusinen
Scala - den smarta kusinenScala - den smarta kusinen
Scala - den smarta kusinenRedpill Linpro
 
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012Amazon Web Services
 
The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196Mahmoud Samir Fayed
 
Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察Tsuyoshi Yamamoto
 
2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin CoroutinesEamonn Boyle
 
The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180Mahmoud Samir Fayed
 
Async all around us (promises)
Async all around us (promises)Async all around us (promises)
Async all around us (promises)Francisco Ferreira
 
The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189Mahmoud Samir Fayed
 
Store and Process Big Data with Hadoop and Cassandra
Store and Process Big Data with Hadoop and CassandraStore and Process Big Data with Hadoop and Cassandra
Store and Process Big Data with Hadoop and CassandraDeependra Ariyadewa
 
Python in the database
Python in the databasePython in the database
Python in the databasepybcn
 
The Ring programming language version 1.5.2 book - Part 11 of 181
The Ring programming language version 1.5.2 book - Part 11 of 181The Ring programming language version 1.5.2 book - Part 11 of 181
The Ring programming language version 1.5.2 book - Part 11 of 181Mahmoud Samir Fayed
 

Was ist angesagt? (20)

The Ring programming language version 1.10 book - Part 50 of 212
The Ring programming language version 1.10 book - Part 50 of 212The Ring programming language version 1.10 book - Part 50 of 212
The Ring programming language version 1.10 book - Part 50 of 212
 
The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185
 
The Ring programming language version 1.5.3 book - Part 40 of 184
The Ring programming language version 1.5.3 book - Part 40 of 184The Ring programming language version 1.5.3 book - Part 40 of 184
The Ring programming language version 1.5.3 book - Part 40 of 184
 
Scala - den smarta kusinen
Scala - den smarta kusinenScala - den smarta kusinen
Scala - den smarta kusinen
 
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
MBL301 Data Persistence to Amazon Dynamodb for Mobile Apps - AWS re: Invent 2012
 
Why realm?
Why realm?Why realm?
Why realm?
 
The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196
 
Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察Jggug 2010 330 Grails 1.3 観察
Jggug 2010 330 Grails 1.3 観察
 
Firebase ng2 zurich
Firebase ng2 zurichFirebase ng2 zurich
Firebase ng2 zurich
 
2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines2019-01-29 - Demystifying Kotlin Coroutines
2019-01-29 - Demystifying Kotlin Coroutines
 
The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180
 
Async all around us (promises)
Async all around us (promises)Async all around us (promises)
Async all around us (promises)
 
Codable routing
Codable routingCodable routing
Codable routing
 
The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189
 
Caching a page
Caching a pageCaching a page
Caching a page
 
Store and Process Big Data with Hadoop and Cassandra
Store and Process Big Data with Hadoop and CassandraStore and Process Big Data with Hadoop and Cassandra
Store and Process Big Data with Hadoop and Cassandra
 
XTW_Import
XTW_ImportXTW_Import
XTW_Import
 
Python in the database
Python in the databasePython in the database
Python in the database
 
Finding Clojure
Finding ClojureFinding Clojure
Finding Clojure
 
The Ring programming language version 1.5.2 book - Part 11 of 181
The Ring programming language version 1.5.2 book - Part 11 of 181The Ring programming language version 1.5.2 book - Part 11 of 181
The Ring programming language version 1.5.2 book - Part 11 of 181
 

Ähnlich wie Kitura Todolist tutorial

Overview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web FrameworkOverview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web FrameworkIndicThreads
 
Scala based Lift Framework
Scala based Lift FrameworkScala based Lift Framework
Scala based Lift Frameworkvhazrati
 
GDG Devfest 2019 - Build go kit microservices at kubernetes with ease
GDG Devfest 2019 - Build go kit microservices at kubernetes with easeGDG Devfest 2019 - Build go kit microservices at kubernetes with ease
GDG Devfest 2019 - Build go kit microservices at kubernetes with easeKAI CHU CHUNG
 
Threads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOSThreads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOSTechWell
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeMacoscope
 
Spring data iii
Spring data iiiSpring data iii
Spring data iii명철 강
 
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...julien.ponge
 
Advanced #2 networking
Advanced #2   networkingAdvanced #2   networking
Advanced #2 networkingVitali Pekelis
 
Serverless archtiectures
Serverless archtiecturesServerless archtiectures
Serverless archtiecturesIegor Fadieiev
 
Android Automated Testing
Android Automated TestingAndroid Automated Testing
Android Automated Testingroisagiv
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js frameworkBen Lin
 
Scala4sling
Scala4slingScala4sling
Scala4slingday
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
G*ワークショップ in 仙台 Grails(とことん)入門
G*ワークショップ in 仙台 Grails(とことん)入門G*ワークショップ in 仙台 Grails(とことん)入門
G*ワークショップ in 仙台 Grails(とことん)入門Tsuyoshi Yamamoto
 

Ähnlich wie Kitura Todolist tutorial (20)

Overview Of Lift Framework
Overview Of Lift FrameworkOverview Of Lift Framework
Overview Of Lift Framework
 
Overview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web FrameworkOverview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web Framework
 
Scala based Lift Framework
Scala based Lift FrameworkScala based Lift Framework
Scala based Lift Framework
 
GDG Devfest 2019 - Build go kit microservices at kubernetes with ease
GDG Devfest 2019 - Build go kit microservices at kubernetes with easeGDG Devfest 2019 - Build go kit microservices at kubernetes with ease
GDG Devfest 2019 - Build go kit microservices at kubernetes with ease
 
Threads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOSThreads, Queues, and More: Async Programming in iOS
Threads, Queues, and More: Async Programming in iOS
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
Server Side Swift: Vapor
Server Side Swift: VaporServer Side Swift: Vapor
Server Side Swift: Vapor
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
 
Spring data iii
Spring data iiiSpring data iii
Spring data iii
 
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
 
Scala on Your Phone
Scala on Your PhoneScala on Your Phone
Scala on Your Phone
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
Advanced #2 networking
Advanced #2   networkingAdvanced #2   networking
Advanced #2 networking
 
Serverless archtiectures
Serverless archtiecturesServerless archtiectures
Serverless archtiectures
 
Android Automated Testing
Android Automated TestingAndroid Automated Testing
Android Automated Testing
 
How and why i roll my own node.js framework
How and why i roll my own node.js frameworkHow and why i roll my own node.js framework
How and why i roll my own node.js framework
 
Scala4sling
Scala4slingScala4sling
Scala4sling
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
G*ワークショップ in 仙台 Grails(とことん)入門
G*ワークショップ in 仙台 Grails(とことん)入門G*ワークショップ in 仙台 Grails(とことん)入門
G*ワークショップ in 仙台 Grails(とことん)入門
 
Nancy + rest mow2012
Nancy + rest   mow2012Nancy + rest   mow2012
Nancy + rest mow2012
 

Kürzlich hochgeladen

Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceanilsa9823
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 

Kürzlich hochgeladen (20)

Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 

Kitura Todolist tutorial

  • 2. Creating a TodoList → Creating a project → Add dependencies → Simple Routing → Error Handling → Promises → Testing
  • 3. Create a Project mkdir TodoList cd TodoList swift package init swift package generate-xcodeproj
  • 4. Add Dependencies import PackageDescription let package = Package( name: "MyTodoList", dependencies: [ .Package(url: "https://github.com/IBM-Swift/Kitura", majorVersion: 0, minor: 32), .Package(url: "https://github.com/IBM-Swift/HeliumLogger", majorVersion: 0, minor: 17) ] )
  • 5. Simple Route let router = Router() router.get("/") { request, response, next in response.status(.OK).send("Hello World!") }
  • 6. Simple Server Kitura.addHTTPServer(onPort: 8090, with: todoListController.router) Kitura.run()
  • 8. Using multiple targets targets: [ Target(name: "Server", dependencies: [.Target(name: "TodoList")]), Target(name: "TodoList") ], Separation project to: → Sources/TodoList/TodoList.swift → Sources/Server/main.swift
  • 9. Create a Controller public final class TodoListController { public let router = Router() public init() { router.get("/v1/tasks", handler: handleGetTasks) router.post("/v1/tasks", handler: handlerAddTask) } }
  • 10. Add routes func handleGetTasks(request: RouterRequest, response: RouterResponse, next: @escaping () -> Void) throws { } func handleAddTask(request: RouterRequest, response: RouterResponse, next: @escaping () -> Void) throws { }
  • 11. Add basic collection to Controller let tasks: [String] = []
  • 12. Get tasks func handleGetTasks(request: RouterRequest, response: RouterResponse, next: @escaping () -> Void) throws { response.status(.OK).send(json: JSON( tasks )) }
  • 13. Add ability to add tasks
  • 14. Add a Body Parser router.all("*", middleware: BodyParser())
  • 15. Simplify getting the JSON back extension RouterRequest { var json: JSON? { guard let body = self.body else { return nil } guard case let .json(json) = body else { return nil } return json } }
  • 16. Get the description back func handleAddTask(request: RouterRequest, response: RouterResponse, next: @escaping () -> Void) throws { if let json = request.json else { response.status(.badRequest) next() return } let description = json["description"].stringValue tasks.append(description) }
  • 17. Protect your array let queue = DispatchQueue(label: "com.example.tasklist") queue.sync { }
  • 18. Create a more rich Task struct Task { let id: UUID let description: String let createdAt: Date let isCompleted: Bool }
  • 19. Make it Equatible extension Task: Equatable { } func == (lhs: Task, rhs: Task) -> Bool { if lhs.id == rhs.id, lhs.description == rhs.description, lhs.createdAt == rhs.createdAt, lhs.isCompleted == rhs.isCompleted { return true } return false }
  • 20. Make things tranformable to Dictionary typealias StringValuePair = [String: Any] protocol StringValuePairConvertible { var stringValuePairs: StringValuePair {get} }
  • 21. Make collections also tranformable to Dictionary extension Array where Element : StringValuePairConvertible { var stringValuePairs: [StringValuePair] { return self.map { $0.stringValuePairs } } }
  • 22. Make Task a StringValuePairConvertible extension Task: StringValuePairConvertible { var stringValuePairs: StringValuePair { return [ "id": "(self.id)", "description": self.description, "createdAt": self.createdAt.timeIntervalSinceReferenceDate, "isCompleted": self.isCompleted ] } }
  • 23. Change [String] to [Task] private var tasks: [Task] = [] response.status(.OK).send(json: JSON(task.stringValuePairs))
  • 24. Add task with Tasks task.append(Task(id: UUID(), description: "Do the dishes", createdAt: Date(), isCompleted: false))
  • 25. Factor out the Database final class TaskDatabase { private var storage: [Task] = [] let queue = DispatchQueue(label: "com.example.tasklist") func addTask(oncompletion: (Task) -> Void) { queue.sync { self.storage.append(task) oncompletion(task) } } func getTasks(oncompletion: ([Task]) -> Void) { queue.sync { oncompletion(self.storage) } } }
  • 28. TaskListError enum TaskListError : LocalizedError { case descriptionTooShort(String) case descriptionTooLong(String) case noJSON
  • 29. Error Description var errorDescription: String? { switch self { case .descriptionTooShort(let string): return "(string) is too short" case .descriptionTooLong(let string): return "(string) is too long" case .noJSON: return "No JSON in payload" } }
  • 30. Make it convertible to JSON extension TaskListError: StringValuePairConvertible { var stringValuePairs: StringValuePair { return ["error": self.errorDescription ?? ""] } }
  • 31. Validating the Request let maximumLength = 40 let minimumLength = 3 struct AddTaskRequest { let description: String }
  • 32. Validate the request func validateRequest(request: RouterRequest) throws -> AddTaskRequest { guard let json = request.json else { throw TaskListError.noJSON } let description = json["description"].stringValue if description.characters.count > maximumLength { throw TaskListError.descriptionTooLong(description) } if description.characters.count < minimumLength { throw TaskListError.descriptionTooShort(description) } return AddTaskRequest(description: description) }
  • 35. Create Promises final class TaskDatabase { private var storage: [Task] = [] let queue = DispatchQueue(label: "com.example.tasklist") func addTask(task: Task) -> Promise<Task> { return Promise{ fulfill, reject in queue.sync { self.storage.append(task) fulfill(task) } } } func getTasks() -> Promise<[Task]> { return Promise{ fulfill, reject in queue.sync { fulfill(self.storage) } } } }
  • 36. Use the Promises _ = firstly { taskDatabase.getTasks() }.then (on: self.queue) { tasks in response.status(.OK).send(json: JSON(tasks.stringValuePairs)) } .catch (on: self.queue) { error in if let err = error as? TaskListError { response.status(.badRequest).send(json: JSON(err.stringValuePairs)) } } .always(on: self.queue) { next() }
  • 37. Use the Promises _ = firstly { () throws -> Promise<Task> in let addRequest = try validateRequest(request: request) let task = Task(with: addRequest) return taskDatabase.addTask(task: task) } .then (on: self.queue) { task -> Void in response.status(.OK).send(json: JSON(task.stringValuePairs)) } .catch (on: self.queue) { error in if let err = error as? TaskListError { response.status(.badRequest).send(json: JSON(err.stringValuePairs)) } } .always(on: self.queue) { next() }
  • 39. Set up Kitura framework private let queue = DispatchQueue(label: "Kitura runloop", qos: .userInitiated, attributes: .concurrent) public let defaultSession = URLSession(configuration: .default) private let todoListController = TodoListController() override func setUp() { super.setUp() Kitura.addHTTPServer(onPort: 8090, with: todoListController.router) queue.async { Kitura.run() } }
  • 40. Add a test func testGetTodos() { let expectation1 = expectation(description: "Get Todos") var url: URLRequest = URLRequest(url: URL(string: "http://localhost:8090/v1/tasks")!) url.addValue("application/json", forHTTPHeaderField: "Content-Type") url.httpMethod = "GET" url.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData let dataTask = defaultSession.dataTask(with: url) { data, response, error in XCTAssertNil(error) switch (response as? HTTPURLResponse)?.statusCode { case 200?: guard let data = data else { XCTAssert(false) return } let json = JSON(data: data) print(json) expectation1.fulfill() case nil: XCTFail("response not HTTPURLResponse") case let code?: XCTFail("bad status: (code)") } } dataTask.resume() waitForExpectations(timeout: 10, handler: { _ in }) }
  • 41. Enable Code coverage swift package generate-xcodeproj --enable-code-coverage