diff --git a/build/2.0/sitemap.xml b/build/2.0/sitemap.xml index 897e570a..fc320eac 100644 --- a/build/2.0/sitemap.xml +++ b/build/2.0/sitemap.xml @@ -4,7 +4,7 @@ / - 2018-05-10 + 2018-05-22 daily @@ -13,37 +13,37 @@ /getting-started/install-on-macos/ - 2018-05-10 + 2018-05-22 daily /getting-started/install-on-ubuntu/ - 2018-05-10 + 2018-05-22 daily /getting-started/toolbox/ - 2018-05-10 + 2018-05-22 daily /getting-started/hello-world/ - 2018-05-10 + 2018-05-22 daily /getting-started/manual/ - 2018-05-10 + 2018-05-22 daily /getting-started/xcode/ - 2018-05-10 + 2018-05-22 daily @@ -53,49 +53,49 @@ /vapor/folder-structure/ - 2018-05-10 + 2018-05-22 daily /vapor/droplet/ - 2018-05-10 + 2018-05-22 daily /vapor/views/ - 2018-05-10 + 2018-05-22 daily /vapor/controllers/ - 2018-05-10 + 2018-05-22 daily /vapor/provider/ - 2018-05-10 + 2018-05-22 daily /vapor/hash/ - 2018-05-10 + 2018-05-22 daily /vapor/log/ - 2018-05-10 + 2018-05-22 daily /vapor/commands/ - 2018-05-10 + 2018-05-22 daily @@ -105,7 +105,7 @@ /configs/config/ - 2018-05-10 + 2018-05-22 daily @@ -115,13 +115,13 @@ /json/package/ - 2018-05-10 + 2018-05-22 daily /json/overview/ - 2018-05-10 + 2018-05-22 daily @@ -131,31 +131,31 @@ /routing/package/ - 2018-05-10 + 2018-05-22 daily /routing/overview/ - 2018-05-10 + 2018-05-22 daily /routing/parameters/ - 2018-05-10 + 2018-05-22 daily /routing/group/ - 2018-05-10 + 2018-05-22 daily /routing/collection/ - 2018-05-10 + 2018-05-22 daily @@ -165,37 +165,37 @@ /fluent/package/ - 2018-05-10 + 2018-05-22 daily /fluent/getting-started/ - 2018-05-10 + 2018-05-22 daily /fluent/model/ - 2018-05-10 + 2018-05-22 daily /fluent/database/ - 2018-05-10 + 2018-05-22 daily /fluent/query/ - 2018-05-10 + 2018-05-22 daily /fluent/relations/ - 2018-05-10 + 2018-05-22 daily @@ -205,13 +205,13 @@ /cache/package/ - 2018-05-10 + 2018-05-22 daily /cache/overview/ - 2018-05-10 + 2018-05-22 daily @@ -221,19 +221,19 @@ /mysql/package/ - 2018-05-10 + 2018-05-22 daily /mysql/provider/ - 2018-05-10 + 2018-05-22 daily /mysql/driver/ - 2018-05-10 + 2018-05-22 daily @@ -243,13 +243,13 @@ /redis/package/ - 2018-05-10 + 2018-05-22 daily /redis/provider/ - 2018-05-10 + 2018-05-22 daily @@ -259,43 +259,43 @@ /auth/package/ - 2018-05-10 + 2018-05-22 daily /auth/provider/ - 2018-05-10 + 2018-05-22 daily /auth/getting-started/ - 2018-05-10 + 2018-05-22 daily /auth/helper/ - 2018-05-10 + 2018-05-22 daily /auth/password/ - 2018-05-10 + 2018-05-22 daily /auth/persist/ - 2018-05-10 + 2018-05-22 daily /auth/redirect-middleware/ - 2018-05-10 + 2018-05-22 daily @@ -305,13 +305,13 @@ /jwt/package/ - 2018-05-10 + 2018-05-22 daily /jwt/overview/ - 2018-05-10 + 2018-05-22 daily @@ -321,13 +321,13 @@ /sessions/package/ - 2018-05-10 + 2018-05-22 daily /sessions/sessions/ - 2018-05-10 + 2018-05-22 daily @@ -337,61 +337,61 @@ /http/package/ - 2018-05-10 + 2018-05-22 daily /http/request/ - 2018-05-10 + 2018-05-22 daily /http/response/ - 2018-05-10 + 2018-05-22 daily /http/middleware/ - 2018-05-10 + 2018-05-22 daily /http/body/ - 2018-05-10 + 2018-05-22 daily /http/response-representable/ - 2018-05-10 + 2018-05-22 daily /http/responder/ - 2018-05-10 + 2018-05-22 daily /http/client/ - 2018-05-10 + 2018-05-22 daily /http/server/ - 2018-05-10 + 2018-05-22 daily /http/cors/ - 2018-05-10 + 2018-05-22 daily @@ -401,19 +401,19 @@ /leaf/package/ - 2018-05-10 + 2018-05-22 daily /leaf/provider/ - 2018-05-10 + 2018-05-22 daily /leaf/leaf/ - 2018-05-10 + 2018-05-22 daily @@ -423,13 +423,13 @@ /validation/package/ - 2018-05-10 + 2018-05-22 daily /validation/overview/ - 2018-05-10 + 2018-05-22 daily @@ -439,13 +439,13 @@ /node/package/ - 2018-05-10 + 2018-05-22 daily /node/getting-started/ - 2018-05-10 + 2018-05-22 daily @@ -455,13 +455,13 @@ /core/package/ - 2018-05-10 + 2018-05-22 daily /core/overview/ - 2018-05-10 + 2018-05-22 daily @@ -471,13 +471,13 @@ /bits/package/ - 2018-05-10 + 2018-05-22 daily /bits/overview/ - 2018-05-10 + 2018-05-22 daily @@ -487,13 +487,13 @@ /debugging/package/ - 2018-05-10 + 2018-05-22 daily /debugging/overview/ - 2018-05-10 + 2018-05-22 daily @@ -503,25 +503,25 @@ /deploy/cloud/ - 2018-05-10 + 2018-05-22 daily /deploy/nginx/ - 2018-05-10 + 2018-05-22 daily /deploy/apache2/ - 2018-05-10 + 2018-05-22 daily /deploy/supervisor/ - 2018-05-10 + 2018-05-22 daily @@ -531,25 +531,25 @@ /version/1_5/ - 2018-05-10 + 2018-05-22 daily /version/2_0/ - 2018-05-10 + 2018-05-22 daily /version/3_0/ - 2018-05-10 + 2018-05-22 daily /version/support/ - 2018-05-10 + 2018-05-22 daily diff --git a/build/3.0/command/overview/index.html b/build/3.0/command/overview/index.html index 09e927aa..f29aba89 100644 --- a/build/3.0/command/overview/index.html +++ b/build/3.0/command/overview/index.html @@ -2222,7 +2222,7 @@ Options: ... /// See `Command`. - func run(using context: CommandContext) throws -> Future { + func run(using context: CommandContext) throws -> Future<Void> { let message = try context.argument("message") /// We can use requireOption here since both options have default values let eyes = try context.requireOption("eyes") diff --git a/build/3.0/fluent/migrations/index.html b/build/3.0/fluent/migrations/index.html index 748c3277..675a650c 100644 --- a/build/3.0/fluent/migrations/index.html +++ b/build/3.0/fluent/migrations/index.html @@ -2139,7 +2139,7 @@ we will use the .create(...) function on the supplied database conn
extension User: Migration {
     /// See Migration.prepare
     static func prepare(on connection: MySQLConnection) -> Future<Void> {
-        return connection.create(self) { builder in
+        return MySQLDatabase.create(self, on: connection) { builder in
             try builder.field(for: \.id)
             try builder.field(for: \.name)
             try builder.field(for: \.age)
@@ -2169,7 +2169,7 @@ app with the --revert option. 

extension User: Migration {
     /// See Migration.revert
     static func revert(on connection: MySQLConnection) -> Future<Void> {
-        return connection.delete(self)
+        return MySQLDatabase.delete(self, on: connection)
     }
 }
 
@@ -2180,7 +2180,7 @@ app with the --revert option.

extension TestUser: Migration {
     /// See Migration.prepare
     static func prepare(on connection: SQLiteConnection) -> Future<Void> {
-        return connection.create(self) { builder in
+        return SQLiteDatabase.create(self, on: connection) { builder in
             try builder.field(for: \.id)
             try builder.field(for: \.name)
             try builder.field(for: \.age)
@@ -2189,7 +2189,7 @@ app with the --revert option. 

/// See Migration.revert static func revert(on connection: SQLiteConnection) -> Future<Void> { - return connection.delete(self) + return SQLiteDatabase.delete(self, on: connection) } }
diff --git a/build/3.0/getting-started/hello-world/index.html b/build/3.0/getting-started/hello-world/index.html index 29e1a105..392f9ea6 100644 --- a/build/3.0/getting-started/hello-world/index.html +++ b/build/3.0/getting-started/hello-world/index.html @@ -2111,7 +2111,7 @@ This will allow us to build and run our app from inside of Xcode, just like an i

The toolbox will ask you if you'd like to open Xcode automatically, select yes.

Build & Run

-

You should now have Xcode open and running. Select the run scheme from the scheme menu, +

You should now have Xcode open and running. Select the run scheme from the scheme menu and My Mac as the deployment target, then click the play button.

You should see the terminal pop up at the bottom of the screen.

Server starting on http://localhost:8080
diff --git a/build/3.0/leaf/basics/index.html b/build/3.0/leaf/basics/index.html
index 7035846a..8ea1d96a 100644
--- a/build/3.0/leaf/basics/index.html
+++ b/build/3.0/leaf/basics/index.html
@@ -2299,7 +2299,7 @@
 

Leaf's engine is completely reactive, supporting both streams and futures. One of the only ones of its kind.

When working with Future results, simply pass the Future in your template context. Streams that carry an encodable type need to be encoded before they're usable within Leaf.

-
struct Profile: Codable {
+
struct Profile: Encodable {
     var friends: EncodableStream
     var currentUser: Future<User>
 }
diff --git a/build/3.0/mysql/fluent/index.html b/build/3.0/mysql/fluent/index.html
index 2fc8cdd1..ec25bfd9 100644
--- a/build/3.0/mysql/fluent/index.html
+++ b/build/3.0/mysql/fluent/index.html
@@ -2269,7 +2269,7 @@
 

Registering the provider will add all of the services required for Fluent MySQL to work properly. It also includes a default database config struct that uses typical development environment credentials.

You can of course override this config struct if you have non-standard credentials.

/// Register custom MySQL Config
-let mysqlConfig = MySQLDatabaseConfig(hostname: "localhost", port: 3306, username: "vapor")
+let mysqlConfig = MySQLDatabaseConfig(hostname: "localhost", port: 3306, username: "vapor", password: "mypassword", database: "mydatabase")
 services.register(mysqlConfig)
 
diff --git a/build/3.0/search/search_index.json b/build/3.0/search/search_index.json index 1030a12b..9eac705c 100644 --- a/build/3.0/search/search_index.json +++ b/build/3.0/search/search_index.json @@ -137,7 +137,7 @@ }, { "location": "/getting-started/hello-world/", - "text": "Hello, world\n\n\nNow that you've installed Vapor, let's create your first Vapor app!\nThis guide will take you step by step through creating a new project, building, and running it.\n\n\nNew Project\n\n\nThe first step is to create a new Vapor project on your computer.\nFor this guide, we will call the project \nHello\n.\n\n\nOpen up your terminal, and use \nVapor Toolbox's \nnew\n command.\n\n\nvapor new Hello\n\n\n\n\n\nOnce that finishes, change into the newly created directory.\n\n\ncd\n Hello\n\n\n\n\n\nGenerate Xcode Project\n\n\nLet's now use the \nVapor Toolbox's \nxcode\n command to generate an Xcode project.\nThis will allow us to build and run our app from inside of Xcode, just like an iOS app.\n\n\nvapor xcode\n\n\n\n\n\nThe toolbox will ask you if you'd like to open Xcode automatically, select \nyes\n.\n\n\nBuild \n Run\n\n\nYou should now have Xcode open and running. Select the \nrun scheme\n from the scheme menu,\nthen click the play button.\n\n\nYou should see the terminal pop up at the bottom of the screen.\n\n\nServer starting on http://localhost:8080\n\n\n\n\n\nVisit Localhost\n\n\nOpen your web browser, and visit \nlocalhost:8080/hello \n\n\nYou should see the following page.\n\n\nHello, world!\n\n\n\n\n\nCongratulations on creating, building, and running your first Vapor app! \ud83c\udf89", + "text": "Hello, world\n\n\nNow that you've installed Vapor, let's create your first Vapor app!\nThis guide will take you step by step through creating a new project, building, and running it.\n\n\nNew Project\n\n\nThe first step is to create a new Vapor project on your computer.\nFor this guide, we will call the project \nHello\n.\n\n\nOpen up your terminal, and use \nVapor Toolbox's \nnew\n command.\n\n\nvapor new Hello\n\n\n\n\n\nOnce that finishes, change into the newly created directory.\n\n\ncd\n Hello\n\n\n\n\n\nGenerate Xcode Project\n\n\nLet's now use the \nVapor Toolbox's \nxcode\n command to generate an Xcode project.\nThis will allow us to build and run our app from inside of Xcode, just like an iOS app.\n\n\nvapor xcode\n\n\n\n\n\nThe toolbox will ask you if you'd like to open Xcode automatically, select \nyes\n.\n\n\nBuild \n Run\n\n\nYou should now have Xcode open and running. Select the \nrun scheme\n from the scheme menu and \nMy Mac\n as the deployment target,\nthen click the play button.\n\n\nYou should see the terminal pop up at the bottom of the screen.\n\n\nServer starting on http://localhost:8080\n\n\n\n\n\nVisit Localhost\n\n\nOpen your web browser, and visit \nlocalhost:8080/hello \n\n\nYou should see the following page.\n\n\nHello, world!\n\n\n\n\n\nCongratulations on creating, building, and running your first Vapor app! \ud83c\udf89", "title": "Hello, world" }, { @@ -157,7 +157,7 @@ }, { "location": "/getting-started/hello-world/#build-run", - "text": "You should now have Xcode open and running. Select the run scheme from the scheme menu,\nthen click the play button. You should see the terminal pop up at the bottom of the screen. Server starting on http://localhost:8080", + "text": "You should now have Xcode open and running. Select the run scheme from the scheme menu and My Mac as the deployment target,\nthen click the play button. You should see the terminal pop up at the bottom of the screen. Server starting on http://localhost:8080", "title": "Build & Run" }, { @@ -717,7 +717,7 @@ }, { "location": "/command/overview/", - "text": "Command Overview\n\n\nThis guide will introduce you to the Command module by showing you how to create your own CLI. For this example, we will implement \ncowsay\n, a command that prints an ASCII picture of a cow with a message.\n\n\n\n\nTip\n\n\nYou can install the real \ncowsay\n program using \nbrew install cowsay\n.\n\n\n\n\n$ cowsay Hello\n -----\n\n Hello \n\n -----\n \n\\ \n ^__^\n \n\\ \n \n(\noo\n\\_\n______\n \n(\n__\n)\n\\ \n \n)\n\\/\\\n\n \n||\n----w \n|\n\n \n||\n \n||\n\n\n\n\n\n\nCommand\n\n\nThe first step is to create a type that conforms to \nCommand\n.\n\n\n/// Generates ASCII picture of a cow with a message.\n\n\nstruct\n \nCowsayCommand\n:\n \nCommand\n \n{\n\n \n...\n\n\n}\n\n\n\n\n\n\nNow let's implement the required methods.\n\n\nArguments\n\n\nCommands can have zero or more \nCommandArgument\ns. These arguments will be required for the command to run.\n\n\n/// Generates ASCII picture of a cow with a message.\n\n\nstruct\n \nCowsayCommand\n:\n \nCommand\n \n{\n\n \n/// See `Command`\n\n \nvar\n \narguments\n:\n \n[\nCommandArgument\n]\n \n{\n\n \nreturn\n \n[.\nargument\n(\nname\n:\n \nmessage\n)]\n\n \n}\n\n\n \n...\n\n\n}\n\n\n\n\n\n\nHere we are defining one argument, the \nmessage\n that the cow will say. This is required to run the \ncowsay\n command.\n\n\nOptions\n\n\nCommands can have zero or more \nCommandOption\ns. These options are not required for the command to run and can be passed using \n--\n or \n-\n syntax.\n\n\n/// Generates ASCII picture of a cow with a message.\n\n\nstruct\n \nCowsayCommand\n:\n \nCommand\n \n{\n\n \n...\n\n \n/// See `Command`\n\n \nvar\n \noptions\n:\n \n[\nCommandOption\n]\n \n{\n\n \nreturn\n \n[\n\n \n.\nvalue\n(\nname\n:\n \neyes\n,\n \nshort\n:\n \ne\n,\n \ndefault\n:\n \noo\n,\n \nhelp\n:\n \n[\nChange cow\ns eyes\n]),\n\n \n.\nvalue\n(\nname\n:\n \ntongue\n,\n \nshort\n:\n \nt\n,\n \ndefault\n:\n \n \n,\n \nhelp\n:\n \n[\nChange cow\ns tongue\n]),\n\n \n]\n\n \n}\n\n \n...\n\n\n}\n\n\n\n\n\n\nHere we are defining two options, \neyes\n and \ntongue\n. These will let the user optionally change how the cow looks.\n\n\nHelp\n\n\nNext we can define an optional help message to display when the user passes \n--help\n.\n\n\n/// Generates ASCII picture of a cow with a message.\n\n\nstruct\n \nCowsayCommand\n:\n \nCommand\n \n{\n\n \n...\n\n \n/// See `Command`\n\n \nvar\n \nhelp\n:\n \n[\nString\n]\n \n{\n\n \nreturn\n \n[\nGenerates ASCII picture of a cow with a message.\n]\n\n \n}\n\n \n...\n\n\n}\n\n\n\n\n\n\nLet's take a look at how this will look once our command is complete:\n\n\nUsage: \nexecutable\n cowsay \nmessage\n \n[\n--eyes,-e\n]\n \n[\n--tongue,-t\n]\n \n\nGenerates ASCII picture of a cow with a message.\n\nArguments:\n message n/a\n\nOptions:\n eyes Change cow\ns eyes\n\n\n tongue Change cow\ns tongue\n\n\n\n\n\nRun\n\n\nFinally, we need to write our implementation:\n\n\n/// Generates ASCII picture of a cow with a message.\n\n\nstruct\n \nCowsayCommand\n:\n \nCommand\n \n{\n\n \n...\n\n\n \n/// See `Command`.\n\n \nfunc\n \nrun\n(\nusing\n \ncontext\n:\n \nCommandContext\n)\n \nthrows\n \n-\n \nFuture\n \n{\n\n \nlet\n \nmessage\n \n=\n \ntry\n \ncontext\n.\nargument\n(\nmessage\n)\n\n \n/// We can use requireOption here since both options have default values\n\n \nlet\n \neyes\n \n=\n \ntry\n \ncontext\n.\nrequireOption\n(\neyes\n)\n\n \nlet\n \ntongue\n \n=\n \ntry\n \ncontext\n.\nrequireOption\n(\ntongue\n)\n\n \nlet\n \npadding\n \n=\n \nString\n(\nrepeating\n:\n \n-\n,\n \ncount\n:\n \nmessage\n.\ncount\n)\n\n \nlet\n \ntext\n:\n \nString\n \n=\n \n\n\n \n\\(\npadding\n)\n\n\n \n \n\\(\nmessage\n)\n \n\n\n \n\\(\npadding\n)\n\n\n \n\\\\\n ^__^\n\n\n \n\\\\\n (\n\\(\neyes\n)\n\\\\\n_______\n\n\n (__)\n\\\\\n )\n\\\\\n/\n\\\\\n\n\n \n\\(\ntongue\n)\n ||----w |\n\n\n || ||\n\n\n \n\n \ncontext\n.\nconsole\n.\nprint\n(\ntext\n)\n\n \nreturn\n \n.\ndone\n(\non\n:\n \ncontext\n.\ncontainer\n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nThe \nCommandContext\n gives you access to everything you will need, including a \nContainer\n. Now that we have a complete \nCommand\n, the next step is to configure it.\n\n\nConfig\n\n\nUse the \nCommandConfig\n struct to register commands to your container. This is usually done in \nconfigure.swift\n\n\n/// Create a `CommandConfig` with default commands.\n\n\nvar\n \ncommandConfig\n \n=\n \nCommandConfig\n.\ndefault\n()\n\n\n/// Add the `CowsayCommand`.\n\n\ncommandConfig\n.\nuse\n(\nCowsayCommand\n(),\n \nas\n:\n \ncowsay\n)\n\n\n/// Register this `CommandConfig` to services.\n\n\nservices\n.\nregister\n(\ncommandConfig\n)\n\n\n\n\n\n\nCheck that your command was properly configured using \n--help\n.\n\n\nswift\n \nrun\n \nRun\n \ncowsay\n \n--\nhelp\n\n\n\n\n\n\nThat's it!\n\n\n$\n \nswift\n \nrun\n \nRun\n \ncowsay\n \nGood\n \njob\n!\n \n-\ne\n \n^^\n \n-\nt\n \nU\n\n \n---------\n\n\n \nGood\n \njob\n!\n \n\n \n---------\n\n \n\\\n \n^\n__\n^\n\n \n\\\n \n(\n^^\n\\\n_______\n\n \n(\n__\n)\n\\\n \n)\n\\\n/\n\\\n\n \nU\n \n||----\nw\n \n|\n\n \n||\n \n||", + "text": "Command Overview\n\n\nThis guide will introduce you to the Command module by showing you how to create your own CLI. For this example, we will implement \ncowsay\n, a command that prints an ASCII picture of a cow with a message.\n\n\n\n\nTip\n\n\nYou can install the real \ncowsay\n program using \nbrew install cowsay\n.\n\n\n\n\n$ cowsay Hello\n -----\n\n Hello \n\n -----\n \n\\ \n ^__^\n \n\\ \n \n(\noo\n\\_\n______\n \n(\n__\n)\n\\ \n \n)\n\\/\\\n\n \n||\n----w \n|\n\n \n||\n \n||\n\n\n\n\n\n\nCommand\n\n\nThe first step is to create a type that conforms to \nCommand\n.\n\n\n/// Generates ASCII picture of a cow with a message.\n\n\nstruct\n \nCowsayCommand\n:\n \nCommand\n \n{\n\n \n...\n\n\n}\n\n\n\n\n\n\nNow let's implement the required methods.\n\n\nArguments\n\n\nCommands can have zero or more \nCommandArgument\ns. These arguments will be required for the command to run.\n\n\n/// Generates ASCII picture of a cow with a message.\n\n\nstruct\n \nCowsayCommand\n:\n \nCommand\n \n{\n\n \n/// See `Command`\n\n \nvar\n \narguments\n:\n \n[\nCommandArgument\n]\n \n{\n\n \nreturn\n \n[.\nargument\n(\nname\n:\n \nmessage\n)]\n\n \n}\n\n\n \n...\n\n\n}\n\n\n\n\n\n\nHere we are defining one argument, the \nmessage\n that the cow will say. This is required to run the \ncowsay\n command.\n\n\nOptions\n\n\nCommands can have zero or more \nCommandOption\ns. These options are not required for the command to run and can be passed using \n--\n or \n-\n syntax.\n\n\n/// Generates ASCII picture of a cow with a message.\n\n\nstruct\n \nCowsayCommand\n:\n \nCommand\n \n{\n\n \n...\n\n \n/// See `Command`\n\n \nvar\n \noptions\n:\n \n[\nCommandOption\n]\n \n{\n\n \nreturn\n \n[\n\n \n.\nvalue\n(\nname\n:\n \neyes\n,\n \nshort\n:\n \ne\n,\n \ndefault\n:\n \noo\n,\n \nhelp\n:\n \n[\nChange cow\ns eyes\n]),\n\n \n.\nvalue\n(\nname\n:\n \ntongue\n,\n \nshort\n:\n \nt\n,\n \ndefault\n:\n \n \n,\n \nhelp\n:\n \n[\nChange cow\ns tongue\n]),\n\n \n]\n\n \n}\n\n \n...\n\n\n}\n\n\n\n\n\n\nHere we are defining two options, \neyes\n and \ntongue\n. These will let the user optionally change how the cow looks.\n\n\nHelp\n\n\nNext we can define an optional help message to display when the user passes \n--help\n.\n\n\n/// Generates ASCII picture of a cow with a message.\n\n\nstruct\n \nCowsayCommand\n:\n \nCommand\n \n{\n\n \n...\n\n \n/// See `Command`\n\n \nvar\n \nhelp\n:\n \n[\nString\n]\n \n{\n\n \nreturn\n \n[\nGenerates ASCII picture of a cow with a message.\n]\n\n \n}\n\n \n...\n\n\n}\n\n\n\n\n\n\nLet's take a look at how this will look once our command is complete:\n\n\nUsage: \nexecutable\n cowsay \nmessage\n \n[\n--eyes,-e\n]\n \n[\n--tongue,-t\n]\n \n\nGenerates ASCII picture of a cow with a message.\n\nArguments:\n message n/a\n\nOptions:\n eyes Change cow\ns eyes\n\n\n tongue Change cow\ns tongue\n\n\n\n\n\nRun\n\n\nFinally, we need to write our implementation:\n\n\n/// Generates ASCII picture of a cow with a message.\n\n\nstruct\n \nCowsayCommand\n:\n \nCommand\n \n{\n\n \n...\n\n\n \n/// See `Command`.\n\n \nfunc\n \nrun\n(\nusing\n \ncontext\n:\n \nCommandContext\n)\n \nthrows\n \n-\n \nFuture\nVoid\n \n{\n\n \nlet\n \nmessage\n \n=\n \ntry\n \ncontext\n.\nargument\n(\nmessage\n)\n\n \n/// We can use requireOption here since both options have default values\n\n \nlet\n \neyes\n \n=\n \ntry\n \ncontext\n.\nrequireOption\n(\neyes\n)\n\n \nlet\n \ntongue\n \n=\n \ntry\n \ncontext\n.\nrequireOption\n(\ntongue\n)\n\n \nlet\n \npadding\n \n=\n \nString\n(\nrepeating\n:\n \n-\n,\n \ncount\n:\n \nmessage\n.\ncount\n)\n\n \nlet\n \ntext\n:\n \nString\n \n=\n \n\n\n \n\\(\npadding\n)\n\n\n \n \n\\(\nmessage\n)\n \n\n\n \n\\(\npadding\n)\n\n\n \n\\\\\n ^__^\n\n\n \n\\\\\n (\n\\(\neyes\n)\n\\\\\n_______\n\n\n (__)\n\\\\\n )\n\\\\\n/\n\\\\\n\n\n \n\\(\ntongue\n)\n ||----w |\n\n\n || ||\n\n\n \n\n \ncontext\n.\nconsole\n.\nprint\n(\ntext\n)\n\n \nreturn\n \n.\ndone\n(\non\n:\n \ncontext\n.\ncontainer\n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nThe \nCommandContext\n gives you access to everything you will need, including a \nContainer\n. Now that we have a complete \nCommand\n, the next step is to configure it.\n\n\nConfig\n\n\nUse the \nCommandConfig\n struct to register commands to your container. This is usually done in \nconfigure.swift\n\n\n/// Create a `CommandConfig` with default commands.\n\n\nvar\n \ncommandConfig\n \n=\n \nCommandConfig\n.\ndefault\n()\n\n\n/// Add the `CowsayCommand`.\n\n\ncommandConfig\n.\nuse\n(\nCowsayCommand\n(),\n \nas\n:\n \ncowsay\n)\n\n\n/// Register this `CommandConfig` to services.\n\n\nservices\n.\nregister\n(\ncommandConfig\n)\n\n\n\n\n\n\nCheck that your command was properly configured using \n--help\n.\n\n\nswift\n \nrun\n \nRun\n \ncowsay\n \n--\nhelp\n\n\n\n\n\n\nThat's it!\n\n\n$\n \nswift\n \nrun\n \nRun\n \ncowsay\n \nGood\n \njob\n!\n \n-\ne\n \n^^\n \n-\nt\n \nU\n\n \n---------\n\n\n \nGood\n \njob\n!\n \n\n \n---------\n\n \n\\\n \n^\n__\n^\n\n \n\\\n \n(\n^^\n\\\n_______\n\n \n(\n__\n)\n\\\n \n)\n\\\n/\n\\\n\n \nU\n \n||----\nw\n \n|\n\n \n||\n \n||", "title": "Overview" }, { @@ -747,7 +747,7 @@ }, { "location": "/command/overview/#run", - "text": "Finally, we need to write our implementation: /// Generates ASCII picture of a cow with a message. struct CowsayCommand : Command { \n ... \n\n /// See `Command`. \n func run ( using context : CommandContext ) throws - Future { \n let message = try context . argument ( message ) \n /// We can use requireOption here since both options have default values \n let eyes = try context . requireOption ( eyes ) \n let tongue = try context . requireOption ( tongue ) \n let padding = String ( repeating : - , count : message . count ) \n let text : String = \\( padding ) \\( message ) \\( padding ) \\\\ ^__^ \\\\ ( \\( eyes ) \\\\ _______ (__) \\\\ ) \\\\ / \\\\ \\( tongue ) ||----w | || || \n context . console . print ( text ) \n return . done ( on : context . container ) \n } } The CommandContext gives you access to everything you will need, including a Container . Now that we have a complete Command , the next step is to configure it.", + "text": "Finally, we need to write our implementation: /// Generates ASCII picture of a cow with a message. struct CowsayCommand : Command { \n ... \n\n /// See `Command`. \n func run ( using context : CommandContext ) throws - Future Void { \n let message = try context . argument ( message ) \n /// We can use requireOption here since both options have default values \n let eyes = try context . requireOption ( eyes ) \n let tongue = try context . requireOption ( tongue ) \n let padding = String ( repeating : - , count : message . count ) \n let text : String = \\( padding ) \\( message ) \\( padding ) \\\\ ^__^ \\\\ ( \\( eyes ) \\\\ _______ (__) \\\\ ) \\\\ / \\\\ \\( tongue ) ||----w | || || \n context . console . print ( text ) \n return . done ( on : context . container ) \n } } The CommandContext gives you access to everything you will need, including a Container . Now that we have a complete Command , the next step is to configure it.", "title": "Run" }, { @@ -1092,7 +1092,7 @@ }, { "location": "/fluent/migrations/", - "text": "Getting Started with Migrations\n\n\nMigrations are a way of making organized, testable, and reliable changes to your database's structure--\neven while it's in production!\n\n\nMigrations are often used for preparing a database schema for your models. However, they can also be used to \nmake normal queries to your database.\n\n\nIn this guide we will cover creating both types of migrations.\n\n\nModel Schema\n\n\nLet's take a look at how we can prepare a schema supporting database to accept the \n\nUser\n model from the \nprevious section\n.\n\n\nJust like we did with the \nModel\n protocol, we will conform our \nUser\n to \nMigration\n.\n\n\nimport\n \nFluent\n\n\n\nextension\n \nUser\n:\n \nMigration\n \n{\n\n\n\n}\n\n\n\n\n\n\nSwift will inform us that \nUser\n does not yet conform. Let's add the required methods!\n\n\nPrepare\n\n\nThe first method to implement is \nprepare\n. This method is where you make any of your \ndesired changes to the database.\n\n\nFor our \nUser\n model, we simply want to create a table that can store one or more users. To do this,\nwe will use the \n.create(...)\n function on the supplied database connection.\n\n\nextension\n \nUser\n:\n \nMigration\n \n{\n\n \n/// See Migration.prepare\n\n \nstatic\n \nfunc\n \nprepare\n(\non\n \nconnection\n:\n \nMySQLConnection\n)\n \n-\n \nFuture\nVoid\n \n{\n\n \nreturn\n \nconnection\n.\ncreate\n(\nself\n)\n \n{\n \nbuilder\n \nin\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nid\n)\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nname\n)\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nage\n)\n\n \n}\n\n \n}\n\n\n}\n\n\n\n\n\n\nWe pass \nself\n (shorthand for \nUser.self\n since this is a static method) as the first argument to the \n.create\n method. This indicates\nto Fluent that we would like to create a schema for the \nUser\n model.\n\n\nNext, we pass a closure that accepts a \nSchemaBuilder\n for our \nUser\n model.\nWe can then call \n.field\non this builder to describe what fields we'd like our table to have.\n\n\nSince we are passing key paths to our \nUser\n model (indicated by \n\\.\n), Fluent can see what type those properties are.\nFor most common types (\nString\n, \nInt\n, \nDouble\n, etc) Fluent will automatically be able to determine the best\ndatabase field type to use.\n\n\nYou can also choose to manually select which database field type to use for a given field.\n\n\ntry\n \nbuilder\n.\nfield\n(\ntype\n:\n \n.\ntext\n,\n \nfor\n:\n \n\\\n.\nname\n)\n\n\n\n\n\n\nLearn more about creating, updating, and deleting schemas in \nFluent \n Schema Builder\n.\n\n\nRevert\n\n\nRevert is the opposite of prepare. Its job is to undo anything that was done in prepare. It is used when you boot your \napp with the \n--revert\n option. \n\n\nTo implement \nrevert\n for our model, we simply use \n.delete\n to indicate that we would like to delete the schema created for \nUser\n.\n\n\nextension\n \nUser\n:\n \nMigration\n \n{\n\n \n/// See Migration.revert\n\n \nstatic\n \nfunc\n \nrevert\n(\non\n \nconnection\n:\n \nMySQLConnection\n)\n \n-\n \nFuture\nVoid\n \n{\n\n \nreturn\n \nconnection\n.\ndelete\n(\nself\n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nExample\n\n\nWe now have a fully functioning model with migration!\n\n\nextension\n \nTestUser\n:\n \nMigration\n \n{\n\n \n/// See Migration.prepare\n\n \nstatic\n \nfunc\n \nprepare\n(\non\n \nconnection\n:\n \nSQLiteConnection\n)\n \n-\n \nFuture\nVoid\n \n{\n\n \nreturn\n \nconnection\n.\ncreate\n(\nself\n)\n \n{\n \nbuilder\n \nin\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nid\n)\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nname\n)\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nage\n)\n\n \n}\n\n \n}\n\n\n \n/// See Migration.revert\n\n \nstatic\n \nfunc\n \nrevert\n(\non\n \nconnection\n:\n \nSQLiteConnection\n)\n \n-\n \nFuture\nVoid\n \n{\n\n \nreturn\n \nconnection\n.\ndelete\n(\nself\n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nDone\n\n\nNow that you have a working Fluent model and migration, you can move onto \nquerying\n your model.", + "text": "Getting Started with Migrations\n\n\nMigrations are a way of making organized, testable, and reliable changes to your database's structure--\neven while it's in production!\n\n\nMigrations are often used for preparing a database schema for your models. However, they can also be used to \nmake normal queries to your database.\n\n\nIn this guide we will cover creating both types of migrations.\n\n\nModel Schema\n\n\nLet's take a look at how we can prepare a schema supporting database to accept the \n\nUser\n model from the \nprevious section\n.\n\n\nJust like we did with the \nModel\n protocol, we will conform our \nUser\n to \nMigration\n.\n\n\nimport\n \nFluent\n\n\n\nextension\n \nUser\n:\n \nMigration\n \n{\n\n\n\n}\n\n\n\n\n\n\nSwift will inform us that \nUser\n does not yet conform. Let's add the required methods!\n\n\nPrepare\n\n\nThe first method to implement is \nprepare\n. This method is where you make any of your \ndesired changes to the database.\n\n\nFor our \nUser\n model, we simply want to create a table that can store one or more users. To do this,\nwe will use the \n.create(...)\n function on the supplied database connection.\n\n\nextension\n \nUser\n:\n \nMigration\n \n{\n\n \n/// See Migration.prepare\n\n \nstatic\n \nfunc\n \nprepare\n(\non\n \nconnection\n:\n \nMySQLConnection\n)\n \n-\n \nFuture\nVoid\n \n{\n\n \nreturn\n \nMySQLDatabase\n.\ncreate\n(\nself\n,\n \non\n:\n \nconnection\n)\n \n{\n \nbuilder\n \nin\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nid\n)\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nname\n)\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nage\n)\n\n \n}\n\n \n}\n\n\n}\n\n\n\n\n\n\nWe pass \nself\n (shorthand for \nUser.self\n since this is a static method) as the first argument to the \n.create\n method. This indicates\nto Fluent that we would like to create a schema for the \nUser\n model.\n\n\nNext, we pass a closure that accepts a \nSchemaBuilder\n for our \nUser\n model.\nWe can then call \n.field\non this builder to describe what fields we'd like our table to have.\n\n\nSince we are passing key paths to our \nUser\n model (indicated by \n\\.\n), Fluent can see what type those properties are.\nFor most common types (\nString\n, \nInt\n, \nDouble\n, etc) Fluent will automatically be able to determine the best\ndatabase field type to use.\n\n\nYou can also choose to manually select which database field type to use for a given field.\n\n\ntry\n \nbuilder\n.\nfield\n(\ntype\n:\n \n.\ntext\n,\n \nfor\n:\n \n\\\n.\nname\n)\n\n\n\n\n\n\nLearn more about creating, updating, and deleting schemas in \nFluent \n Schema Builder\n.\n\n\nRevert\n\n\nRevert is the opposite of prepare. Its job is to undo anything that was done in prepare. It is used when you boot your \napp with the \n--revert\n option. \n\n\nTo implement \nrevert\n for our model, we simply use \n.delete\n to indicate that we would like to delete the schema created for \nUser\n.\n\n\nextension\n \nUser\n:\n \nMigration\n \n{\n\n \n/// See Migration.revert\n\n \nstatic\n \nfunc\n \nrevert\n(\non\n \nconnection\n:\n \nMySQLConnection\n)\n \n-\n \nFuture\nVoid\n \n{\n\n \nreturn\n \nMySQLDatabase\n.\ndelete\n(\nself\n,\n \non\n:\n \nconnection\n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nExample\n\n\nWe now have a fully functioning model with migration!\n\n\nextension\n \nTestUser\n:\n \nMigration\n \n{\n\n \n/// See Migration.prepare\n\n \nstatic\n \nfunc\n \nprepare\n(\non\n \nconnection\n:\n \nSQLiteConnection\n)\n \n-\n \nFuture\nVoid\n \n{\n\n \nreturn\n \nSQLiteDatabase\n.\ncreate\n(\nself\n,\n \non\n:\n \nconnection\n)\n \n{\n \nbuilder\n \nin\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nid\n)\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nname\n)\n\n \ntry\n \nbuilder\n.\nfield\n(\nfor\n:\n \n\\\n.\nage\n)\n\n \n}\n\n \n}\n\n\n \n/// See Migration.revert\n\n \nstatic\n \nfunc\n \nrevert\n(\non\n \nconnection\n:\n \nSQLiteConnection\n)\n \n-\n \nFuture\nVoid\n \n{\n\n \nreturn\n \nSQLiteDatabase\n.\ndelete\n(\nself\n,\n \non\n:\n \nconnection\n)\n\n \n}\n\n\n}\n\n\n\n\n\n\nDone\n\n\nNow that you have a working Fluent model and migration, you can move onto \nquerying\n your model.", "title": "Migrations" }, { @@ -1107,17 +1107,17 @@ }, { "location": "/fluent/migrations/#prepare", - "text": "The first method to implement is prepare . This method is where you make any of your \ndesired changes to the database. For our User model, we simply want to create a table that can store one or more users. To do this,\nwe will use the .create(...) function on the supplied database connection. extension User : Migration { \n /// See Migration.prepare \n static func prepare ( on connection : MySQLConnection ) - Future Void { \n return connection . create ( self ) { builder in \n try builder . field ( for : \\ . id ) \n try builder . field ( for : \\ . name ) \n try builder . field ( for : \\ . age ) \n } \n } } We pass self (shorthand for User.self since this is a static method) as the first argument to the .create method. This indicates\nto Fluent that we would like to create a schema for the User model. Next, we pass a closure that accepts a SchemaBuilder for our User model.\nWe can then call .field on this builder to describe what fields we'd like our table to have. Since we are passing key paths to our User model (indicated by \\. ), Fluent can see what type those properties are.\nFor most common types ( String , Int , Double , etc) Fluent will automatically be able to determine the best\ndatabase field type to use. You can also choose to manually select which database field type to use for a given field. try builder . field ( type : . text , for : \\ . name ) Learn more about creating, updating, and deleting schemas in Fluent Schema Builder .", + "text": "The first method to implement is prepare . This method is where you make any of your \ndesired changes to the database. For our User model, we simply want to create a table that can store one or more users. To do this,\nwe will use the .create(...) function on the supplied database connection. extension User : Migration { \n /// See Migration.prepare \n static func prepare ( on connection : MySQLConnection ) - Future Void { \n return MySQLDatabase . create ( self , on : connection ) { builder in \n try builder . field ( for : \\ . id ) \n try builder . field ( for : \\ . name ) \n try builder . field ( for : \\ . age ) \n } \n } } We pass self (shorthand for User.self since this is a static method) as the first argument to the .create method. This indicates\nto Fluent that we would like to create a schema for the User model. Next, we pass a closure that accepts a SchemaBuilder for our User model.\nWe can then call .field on this builder to describe what fields we'd like our table to have. Since we are passing key paths to our User model (indicated by \\. ), Fluent can see what type those properties are.\nFor most common types ( String , Int , Double , etc) Fluent will automatically be able to determine the best\ndatabase field type to use. You can also choose to manually select which database field type to use for a given field. try builder . field ( type : . text , for : \\ . name ) Learn more about creating, updating, and deleting schemas in Fluent Schema Builder .", "title": "Prepare" }, { "location": "/fluent/migrations/#revert", - "text": "Revert is the opposite of prepare. Its job is to undo anything that was done in prepare. It is used when you boot your \napp with the --revert option. To implement revert for our model, we simply use .delete to indicate that we would like to delete the schema created for User . extension User : Migration { \n /// See Migration.revert \n static func revert ( on connection : MySQLConnection ) - Future Void { \n return connection . delete ( self ) \n } }", + "text": "Revert is the opposite of prepare. Its job is to undo anything that was done in prepare. It is used when you boot your \napp with the --revert option. To implement revert for our model, we simply use .delete to indicate that we would like to delete the schema created for User . extension User : Migration { \n /// See Migration.revert \n static func revert ( on connection : MySQLConnection ) - Future Void { \n return MySQLDatabase . delete ( self , on : connection ) \n } }", "title": "Revert" }, { "location": "/fluent/migrations/#example", - "text": "We now have a fully functioning model with migration! extension TestUser : Migration { \n /// See Migration.prepare \n static func prepare ( on connection : SQLiteConnection ) - Future Void { \n return connection . create ( self ) { builder in \n try builder . field ( for : \\ . id ) \n try builder . field ( for : \\ . name ) \n try builder . field ( for : \\ . age ) \n } \n } \n\n /// See Migration.revert \n static func revert ( on connection : SQLiteConnection ) - Future Void { \n return connection . delete ( self ) \n } }", + "text": "We now have a fully functioning model with migration! extension TestUser : Migration { \n /// See Migration.prepare \n static func prepare ( on connection : SQLiteConnection ) - Future Void { \n return SQLiteDatabase . create ( self , on : connection ) { builder in \n try builder . field ( for : \\ . id ) \n try builder . field ( for : \\ . name ) \n try builder . field ( for : \\ . age ) \n } \n } \n\n /// See Migration.revert \n static func revert ( on connection : SQLiteConnection ) - Future Void { \n return SQLiteDatabase . delete ( self , on : connection ) \n } }", "title": "Example" }, { @@ -1502,7 +1502,7 @@ }, { "location": "/leaf/basics/", - "text": "Basics\n\n\nWelcome to Leaf. Leaf's goal is to be a simple templating language that can make generating views easier. There are plenty of great templating languages, so use what's best for you \u2013 maybe that's Leaf! The goals of Leaf are:\n\n\n\n\nSmall set of strictly enforced rules\n\n\nConsistency\n\n\nParser first mentality\n\n\nExtensibility\n\n\nAsynchronous and reactive\n\n\n\n\nRendering a template\n\n\nOnce you have Leaf installed, you should create a directory called \u201cResources\u201d inside your project folder, and inside that create another directory called \u201cViews\u201d. This Resources/Views directory is the default location for Leaf templates, although you can change it if you want.\n\n\nFirstly, import Leaf to routes.swift\n\n\nimport\n \nLeaf\n\n\n\n\n\n\nThen, to render a basic Leaf template from a route, add this code:\n\n\nrouter\n.\nget\n \n{\n \nreq\n \n-\n \nFuture\nView\n \nin\n\n \nlet\n \nleaf\n \n=\n \ntry\n \nreq\n.\nmake\n(\nLeafRenderer\n.\nself\n)\n\n \nlet\n \ncontext\n \n=\n \n[\nString\n:\n \nString\n]()\n\n \nreturn\n \ntry\n \nleaf\n.\nrender\n(\nhome\n,\n \ncontext\n)\n\n\n}\n\n\n\n\n\n\nThat will load home.leaf in the Resources/Views directory and render it. The \ncontext\n dictionary is there to let you provide custom data to render inside the template, but you might find it easier to use codable structs instead because they provide extra type safety. For example:\n\n\nstruct\n \nHomePage\n:\n \nCodable\n \n{\n\n \nvar\n \ntitle\n:\n \nString\n\n \nvar\n \ncontent\n:\n \nString\n\n\n}\n\n\n\n\n\n\nAsync\n\n\nLeaf's engine is completely reactive, supporting both streams and futures. One of the only ones of its kind.\n\n\nWhen working with Future results, simply pass the \nFuture\n in your template context.\nStreams that carry an encodable type need to be encoded before they're usable within Leaf.\n\n\nstruct\n \nProfile\n:\n \nCodable\n \n{\n\n \nvar\n \nfriends\n:\n \nEncodableStream\n\n \nvar\n \ncurrentUser\n:\n \nFuture\nUser\n\n\n}\n\n\n\n\n\n\nIn the above context, the \ncurrentUser\n variable in Leaf will behave as being a \nUser\n type. Leaf will not read the user Future if it's not used during rendering.\n\n\nEncodableStream\n will behave as an array of LeafData, only with lower memory impact and better performance. It is recommended to use \nEncodableStream\n for (large) database queries.\n\n\nYour name is #(currentUser.name).\n\n#for(friend in friends) {\n #(friend.name) is a friend of you.\n}\n\n\n\n\n\nTemplate syntax\n\n\nStructure\n\n\nLeaf tags are made up of four elements:\n\n\n\n\nToken: \n#\n is the token\n\n\nName: A \nstring\n that identifies the tag\n\n\nParameter List: \n()\n May accept 0 or more arguments\n\n\nBody (optional): \n{}\n Must be separated from the parameter list by a space\n\n\n\n\nThere can be many different usages of these four elements depending on the tag's implementation. Let's look at a few examples of how Leaf's built-in tags might be used:\n\n\n\n\n#()\n\n\n#(variable)\n\n\n#embed(\"template\")\n\n\n#set(\"title\") { Welcome to Vapor }\n\n\n#count(friends)\n\n\n#for(friend in friends) { \nli\n#(friend.name)\n/li\n }\n\n\n\n\nWorking with context\n\n\nIn our Swift example from earlier, we used an empty \n[String: String]\n dictionary for context, which passes no custom data to Leaf. To try rendering content, use this code instead:\n\n\nlet\n \ncontext\n \n=\n \n[\ntitle\n:\n \nWelcome\n,\n \nmessage\n:\n \nVapor and Leaf work hand in hand\n]\n\n\nreturn\n \ntry\n \nleaf\n.\nmake\n(\nhome\n,\n \ncontext\n)\n\n\n\n\n\n\nThat will expose \ntitle\n and \nmessage\n to our Leaf template, which can then be used inside tags. For example:\n\n\nh1\n#(title)\n/h1\n\n\np\n#(message)\n/p\n\n\n\n\n\n\nChecking conditions\n\n\nLeaf is able to evaluate a range of conditions using its \n#if\n tag. For example, if you provide a variable it will check that variable exists in its context:\n\n\n#if(title) {\n The title is #(title)\n} else {\n No title was provided.\n}\n\n\n\n\n\nYou can also write comparisons, for example:\n\n\n#if(title == \nWelcome\n) {\n This is a friendly web page.\n} else {\n No strangers allowed!\n}\n\n\n\n\n\nIf you want to use another tag as part of your condition, you should omit the \n#\n for the inner tag. For example:\n\n\n#if(lowercase(title) == \nwelcome\n) {\n This is a friendly web page.\n} else {\n No strangers allowed!\n}\n\n\n\n\n\nLoops\n\n\nIf you provide an array of items, Leaf can loop over them and let you manipulate each item individually using its \n#for\n tag. For example, we could update our Swift code to provide a list of names in a team:\n\n\nlet\n \ncontext\n \n=\n \n[\nteam\n:\n \n[\nMalcolm\n,\n \nKaylee\n,\n \nJayne\n]]\n\n\n\n\n\n\nWe could then loop over them in Leaf like this:\n\n\n#for(name in team) {\n \np\n#(name) is in the team.\n/p\n\n}\n\n\n\n\n\nLeaf provides some extra variables inside a \n#for\n loop to give you more information about the loop's progress:\n\n\n\n\nThe \nloop.isFirst\n variable is true when the current iteration is the first one.\n\n\nThe \nloop.isLast\n variable is true when it's the last iteration.\n\n\nThe \nloop.index\n variable will be set to the number of the current iteration, counting from 0.\n\n\n\n\nHere's how we could use a loop variable to print just the first name in our array:\n\n\n#for(name in team) {\n #if(isFirst) { \np\n#(name) is first!\n/p\n }\n}\n\n\n\n\n\nEmbedding templates\n\n\nLeaf\u2019s \n#embed\n tag allows you to copy the contents of one template into another. When use this, you should always omit the template file's .leaf extension.\n\n\nEmbedding is useful for copying in a standard piece of content, for example a page footer or advert code:\n\n\n#embed(\nfooter\n)\n\n\n\n\n\nThis tag is also useful for building one template on top of another. For example, you might have a master.leaf file that includes all the code required to lay out your website \u2013\u00a0HTML structure, CSS and JavaScript \u2013\u00a0with some gaps in place that represent where page content varies.\n\n\nUsing this approach, you would construct a child template that fills in its unique content, then embeds the parent template that places the content appropriately.\n\n\nFor example, you might create a child.leaf template like this:\n\n\n#set(\nbody\n) {\n\np\nWelcome to Vapor!\n/p\n\n}\n\n#embed(\nmaster\n)\n\n\n\n\n\nThat configures one item of context, \nbody\n, but doesn\u2019t display it directly. Instead, it embeds master.leaf, which can render \nbody\n along with any other context variables passed in from Swift. For example, master.leaf might look like this:\n\n\nhtml\n\n\nhead\ntitle\n#(title)\n/title\n/head\n\n\nbody\n#get(body)\n/body\n\n\n/html\n\n\n\n\n\n\nWhen given the context \n[\"title\": \"Hi there!\"]\n, child.leaf will render as follows:\n\n\nhtml\n\n\nhead\ntitle\nHi there!\n/title\n/head\n\n\nbody\np\nWelcome to Vapor!\n/p\n/body\n\n\n/html\n\n\n\n\n\n\nOther tags\n\n\n#capitalize\n\n\nThe \n#capitalize\n tag uppercases the first letter of any string. For example, \u201ctaylor\u201d will become \u201cTaylor\u201d.\n\n\n#capitalize(name)\n\n\n\n\n\n#contains\n\n\nThe \n#contains\n tag accepts an array and a value as its two parameters, and returns true if the array in parameter one contains the value in parameter two. For example, given the array \nteam\n:\n\n\n#if(contains(team, \nJayne\n)) {\n You\nre all set!\n} else {\n You need someone to do PR.\n}\n\n\n\n\n\n#count\n\n\nThe \n#count\n tag returns the number of items in an array. For example:\n\n\nYour search matched #count(matches) pages.\n\n\n\n\n\n#lowercase\n\n\nThe \n#lowercase\n tag lowercases all letters in a string. For example, \u201cTaylor\u201d will become \u201ctaylor\u201d.\n\n\n#lowercase(name)\n\n\n\n\n\n#uppercase\n\n\nThe \n#uppercase\n tag uppercases all letters in a string. For example, \u201cTaylor\u201d will become \u201cTAYLOR\u201d.\n\n\n#uppercase(name)", + "text": "Basics\n\n\nWelcome to Leaf. Leaf's goal is to be a simple templating language that can make generating views easier. There are plenty of great templating languages, so use what's best for you \u2013 maybe that's Leaf! The goals of Leaf are:\n\n\n\n\nSmall set of strictly enforced rules\n\n\nConsistency\n\n\nParser first mentality\n\n\nExtensibility\n\n\nAsynchronous and reactive\n\n\n\n\nRendering a template\n\n\nOnce you have Leaf installed, you should create a directory called \u201cResources\u201d inside your project folder, and inside that create another directory called \u201cViews\u201d. This Resources/Views directory is the default location for Leaf templates, although you can change it if you want.\n\n\nFirstly, import Leaf to routes.swift\n\n\nimport\n \nLeaf\n\n\n\n\n\n\nThen, to render a basic Leaf template from a route, add this code:\n\n\nrouter\n.\nget\n \n{\n \nreq\n \n-\n \nFuture\nView\n \nin\n\n \nlet\n \nleaf\n \n=\n \ntry\n \nreq\n.\nmake\n(\nLeafRenderer\n.\nself\n)\n\n \nlet\n \ncontext\n \n=\n \n[\nString\n:\n \nString\n]()\n\n \nreturn\n \ntry\n \nleaf\n.\nrender\n(\nhome\n,\n \ncontext\n)\n\n\n}\n\n\n\n\n\n\nThat will load home.leaf in the Resources/Views directory and render it. The \ncontext\n dictionary is there to let you provide custom data to render inside the template, but you might find it easier to use codable structs instead because they provide extra type safety. For example:\n\n\nstruct\n \nHomePage\n:\n \nCodable\n \n{\n\n \nvar\n \ntitle\n:\n \nString\n\n \nvar\n \ncontent\n:\n \nString\n\n\n}\n\n\n\n\n\n\nAsync\n\n\nLeaf's engine is completely reactive, supporting both streams and futures. One of the only ones of its kind.\n\n\nWhen working with Future results, simply pass the \nFuture\n in your template context.\nStreams that carry an encodable type need to be encoded before they're usable within Leaf.\n\n\nstruct\n \nProfile\n:\n \nEncodable\n \n{\n\n \nvar\n \nfriends\n:\n \nEncodableStream\n\n \nvar\n \ncurrentUser\n:\n \nFuture\nUser\n\n\n}\n\n\n\n\n\n\nIn the above context, the \ncurrentUser\n variable in Leaf will behave as being a \nUser\n type. Leaf will not read the user Future if it's not used during rendering.\n\n\nEncodableStream\n will behave as an array of LeafData, only with lower memory impact and better performance. It is recommended to use \nEncodableStream\n for (large) database queries.\n\n\nYour name is #(currentUser.name).\n\n#for(friend in friends) {\n #(friend.name) is a friend of you.\n}\n\n\n\n\n\nTemplate syntax\n\n\nStructure\n\n\nLeaf tags are made up of four elements:\n\n\n\n\nToken: \n#\n is the token\n\n\nName: A \nstring\n that identifies the tag\n\n\nParameter List: \n()\n May accept 0 or more arguments\n\n\nBody (optional): \n{}\n Must be separated from the parameter list by a space\n\n\n\n\nThere can be many different usages of these four elements depending on the tag's implementation. Let's look at a few examples of how Leaf's built-in tags might be used:\n\n\n\n\n#()\n\n\n#(variable)\n\n\n#embed(\"template\")\n\n\n#set(\"title\") { Welcome to Vapor }\n\n\n#count(friends)\n\n\n#for(friend in friends) { \nli\n#(friend.name)\n/li\n }\n\n\n\n\nWorking with context\n\n\nIn our Swift example from earlier, we used an empty \n[String: String]\n dictionary for context, which passes no custom data to Leaf. To try rendering content, use this code instead:\n\n\nlet\n \ncontext\n \n=\n \n[\ntitle\n:\n \nWelcome\n,\n \nmessage\n:\n \nVapor and Leaf work hand in hand\n]\n\n\nreturn\n \ntry\n \nleaf\n.\nmake\n(\nhome\n,\n \ncontext\n)\n\n\n\n\n\n\nThat will expose \ntitle\n and \nmessage\n to our Leaf template, which can then be used inside tags. For example:\n\n\nh1\n#(title)\n/h1\n\n\np\n#(message)\n/p\n\n\n\n\n\n\nChecking conditions\n\n\nLeaf is able to evaluate a range of conditions using its \n#if\n tag. For example, if you provide a variable it will check that variable exists in its context:\n\n\n#if(title) {\n The title is #(title)\n} else {\n No title was provided.\n}\n\n\n\n\n\nYou can also write comparisons, for example:\n\n\n#if(title == \nWelcome\n) {\n This is a friendly web page.\n} else {\n No strangers allowed!\n}\n\n\n\n\n\nIf you want to use another tag as part of your condition, you should omit the \n#\n for the inner tag. For example:\n\n\n#if(lowercase(title) == \nwelcome\n) {\n This is a friendly web page.\n} else {\n No strangers allowed!\n}\n\n\n\n\n\nLoops\n\n\nIf you provide an array of items, Leaf can loop over them and let you manipulate each item individually using its \n#for\n tag. For example, we could update our Swift code to provide a list of names in a team:\n\n\nlet\n \ncontext\n \n=\n \n[\nteam\n:\n \n[\nMalcolm\n,\n \nKaylee\n,\n \nJayne\n]]\n\n\n\n\n\n\nWe could then loop over them in Leaf like this:\n\n\n#for(name in team) {\n \np\n#(name) is in the team.\n/p\n\n}\n\n\n\n\n\nLeaf provides some extra variables inside a \n#for\n loop to give you more information about the loop's progress:\n\n\n\n\nThe \nloop.isFirst\n variable is true when the current iteration is the first one.\n\n\nThe \nloop.isLast\n variable is true when it's the last iteration.\n\n\nThe \nloop.index\n variable will be set to the number of the current iteration, counting from 0.\n\n\n\n\nHere's how we could use a loop variable to print just the first name in our array:\n\n\n#for(name in team) {\n #if(isFirst) { \np\n#(name) is first!\n/p\n }\n}\n\n\n\n\n\nEmbedding templates\n\n\nLeaf\u2019s \n#embed\n tag allows you to copy the contents of one template into another. When use this, you should always omit the template file's .leaf extension.\n\n\nEmbedding is useful for copying in a standard piece of content, for example a page footer or advert code:\n\n\n#embed(\nfooter\n)\n\n\n\n\n\nThis tag is also useful for building one template on top of another. For example, you might have a master.leaf file that includes all the code required to lay out your website \u2013\u00a0HTML structure, CSS and JavaScript \u2013\u00a0with some gaps in place that represent where page content varies.\n\n\nUsing this approach, you would construct a child template that fills in its unique content, then embeds the parent template that places the content appropriately.\n\n\nFor example, you might create a child.leaf template like this:\n\n\n#set(\nbody\n) {\n\np\nWelcome to Vapor!\n/p\n\n}\n\n#embed(\nmaster\n)\n\n\n\n\n\nThat configures one item of context, \nbody\n, but doesn\u2019t display it directly. Instead, it embeds master.leaf, which can render \nbody\n along with any other context variables passed in from Swift. For example, master.leaf might look like this:\n\n\nhtml\n\n\nhead\ntitle\n#(title)\n/title\n/head\n\n\nbody\n#get(body)\n/body\n\n\n/html\n\n\n\n\n\n\nWhen given the context \n[\"title\": \"Hi there!\"]\n, child.leaf will render as follows:\n\n\nhtml\n\n\nhead\ntitle\nHi there!\n/title\n/head\n\n\nbody\np\nWelcome to Vapor!\n/p\n/body\n\n\n/html\n\n\n\n\n\n\nOther tags\n\n\n#capitalize\n\n\nThe \n#capitalize\n tag uppercases the first letter of any string. For example, \u201ctaylor\u201d will become \u201cTaylor\u201d.\n\n\n#capitalize(name)\n\n\n\n\n\n#contains\n\n\nThe \n#contains\n tag accepts an array and a value as its two parameters, and returns true if the array in parameter one contains the value in parameter two. For example, given the array \nteam\n:\n\n\n#if(contains(team, \nJayne\n)) {\n You\nre all set!\n} else {\n You need someone to do PR.\n}\n\n\n\n\n\n#count\n\n\nThe \n#count\n tag returns the number of items in an array. For example:\n\n\nYour search matched #count(matches) pages.\n\n\n\n\n\n#lowercase\n\n\nThe \n#lowercase\n tag lowercases all letters in a string. For example, \u201cTaylor\u201d will become \u201ctaylor\u201d.\n\n\n#lowercase(name)\n\n\n\n\n\n#uppercase\n\n\nThe \n#uppercase\n tag uppercases all letters in a string. For example, \u201cTaylor\u201d will become \u201cTAYLOR\u201d.\n\n\n#uppercase(name)", "title": "Basics" }, { @@ -1517,7 +1517,7 @@ }, { "location": "/leaf/basics/#async", - "text": "Leaf's engine is completely reactive, supporting both streams and futures. One of the only ones of its kind. When working with Future results, simply pass the Future in your template context.\nStreams that carry an encodable type need to be encoded before they're usable within Leaf. struct Profile : Codable { \n var friends : EncodableStream \n var currentUser : Future User } In the above context, the currentUser variable in Leaf will behave as being a User type. Leaf will not read the user Future if it's not used during rendering. EncodableStream will behave as an array of LeafData, only with lower memory impact and better performance. It is recommended to use EncodableStream for (large) database queries. Your name is #(currentUser.name).\n\n#for(friend in friends) {\n #(friend.name) is a friend of you.\n}", + "text": "Leaf's engine is completely reactive, supporting both streams and futures. One of the only ones of its kind. When working with Future results, simply pass the Future in your template context.\nStreams that carry an encodable type need to be encoded before they're usable within Leaf. struct Profile : Encodable { \n var friends : EncodableStream \n var currentUser : Future User } In the above context, the currentUser variable in Leaf will behave as being a User type. Leaf will not read the user Future if it's not used during rendering. EncodableStream will behave as an array of LeafData, only with lower memory impact and better performance. It is recommended to use EncodableStream for (large) database queries. Your name is #(currentUser.name).\n\n#for(friend in friends) {\n #(friend.name) is a friend of you.\n}", "title": "Async" }, { @@ -1702,7 +1702,7 @@ }, { "location": "/mysql/fluent/", - "text": "Fluent MySQL\n\n\nFluent MySQL (\nvapor/fluent-mysql\n) is a type-safe, fast, and easy-to-use ORM for MySQL built on top of \nFluent\n.\n\n\n\n\nSeealso\n\n\nThe Fluent MySQL package is built on top of \nFluent\n and the pure Swift, NIO-based \nMySQL core\n. You should refer to their guides for more information about subjects not covered here.\n\n\n\n\nGetting Started\n\n\nThis section will show you how to add Fluent MySQL to your project and create your first \nMySQLModel\n.\n\n\nPackage\n\n\nThe first step to using Fluent MySQL is adding it as a dependency to your project in your SPM package manifest file.\n\n\n// swift-tools-version:4.0\n\n\nimport\n \nPackageDescription\n\n\n\nlet\n \npackage\n \n=\n \nPackage\n(\n\n \nname\n:\n \nMyApp\n,\n\n \ndependencies\n:\n \n[\n\n \n/// Any other dependencies ...\n\n\n \n// \ud83d\udd8b\ud83d\udc2c Swift ORM (queries, models, relations, etc) built on MySQL.\n\n \n.\npackage\n(\nurl\n:\n \nhttps://github.com/vapor/fluent-mysql.git\n,\n \nfrom\n:\n \n3.0.0-rc\n),\n\n \n],\n\n \ntargets\n:\n \n[\n\n \n.\ntarget\n(\nname\n:\n \nApp\n,\n \ndependencies\n:\n \n[\nFluentMySQL\n,\n \n...]),\n\n \n.\ntarget\n(\nname\n:\n \nRun\n,\n \ndependencies\n:\n \n[\nApp\n]),\n\n \n.\ntestTarget\n(\nname\n:\n \nAppTests\n,\n \ndependencies\n:\n \n[\nApp\n]),\n\n \n]\n\n\n)\n\n\n\n\n\n\nDon't forget to add the module as a dependency in the \ntargets\n array. Once you have added the dependency, regenerate your Xcode project with the following command:\n\n\nvapor xcode\n\n\n\n\n\nModel\n\n\nNow let's create our first \nMySQLModel\n. Models represent tables in your MySQL database and they are the primary method of interacting with your data. \n\n\n/// A simple user.\n\n\nfinal\n \nclass\n \nUser\n:\n \nMySQLModel\n \n{\n\n \n/// The unique identifier for this user.\n\n \nvar\n \nid\n:\n \nInt\n?\n\n\n \n/// The user\ns full name.\n\n \nvar\n \nname\n:\n \nString\n\n\n \n/// The user\ns current age in years.\n\n \nvar\n \nage\n:\n \nInt\n\n\n \n/// Creates a new user.\n\n \ninit\n(\nid\n:\n \nInt\n?\n \n=\n \nnil\n,\n \nname\n:\n \nString\n,\n \nage\n:\n \nInt\n)\n \n{\n\n \nself\n.\nid\n \n=\n \nid\n\n \nself\n.\nname\n \n=\n \nname\n\n \nself\n.\nage\n \n=\n \nage\n\n \n}\n\n\n}\n\n\n\n\n\n\nThe example above shows a \nMySQLModel\n for a simple model representing a user. You can make both \nstruct\ns and \nclass\nes a model. You can even conform types that come from external modules. The only requirement is that these types conform to \nCodable\n, which must be declared on the base type for synthesized (automatic) conformance.\n\n\nStandard practice with MySQL databases is using an auto-generated \nINTEGER\n for creating and storing unique identifiers in the \nid\n column. It's also possible to use \nUUID\ns or even \nString\ns for your identifiers. There are convenience protocol for that. \n\n\n\n\n\n\n\n\nprotocol\n\n\ntype\n\n\nkey\n\n\n\n\n\n\n\n\n\n\nMySQLModel\n\n\nInt\n\n\nid\n\n\n\n\n\n\nMySQLUUIDModel\n\n\nUUID\n\n\nid\n\n\n\n\n\n\nMySQLStringModel\n\n\nString\n\n\nid\n\n\n\n\n\n\n\n\n\n\nSeealso\n\n\nTake a look at \nFluent \n Model\n for more information on creating models with custom ID types and keys.\n\n\n\n\nMigration\n\n\nAll of your models (with some rare exceptions) should have a corresponding table\nor \nschema\nin your database. You can use a \nFluent \n Migration\n to automatically generate this schema in a testable, maintainable way. Fluent makes it easy to automatically generate a migration for your model\n\n\n\n\nTip\n\n\nIf you are creating models to represent an existing table or database, you can skip this step.\n\n\n\n\n/// Allows `User` to be used as a migration.\n\n\nextension\n \nUser\n:\n \nMigration\n \n{\n \n}\n\n\n\n\n\n\nThat's all it takes. Fluent uses Codable to analyze your model and will attempt to create the best possible schema for it.\n\n\nTake a look at \nFluent \n Migration\n if you are interested in customizing this migration.\n\n\nConfigure\n\n\nThe final step is to configure your database. At a minimum, this requires adding two things to your \nconfigure.swift\n file.\n\n\n\n\nFluentMySQLProvider\n\n\nMigrationConfig\n\n\n\n\nLet's take a look.\n\n\nimport\n \nFluentMySQL\n\n\n\n/// ...\n\n\n\n/// Register providers first\n\n\ntry\n \nservices\n.\nregister\n(\nFluentMySQLProvider\n())\n\n\n\n/// Configure migrations\n\n\nvar\n \nmigrations\n \n=\n \nMigrationConfig\n()\n\n\nmigrations\n.\nadd\n(\nmodel\n:\n \nUser\n.\nself\n,\n \ndatabase\n:\n \n.\nmysql\n)\n\n\nservices\n.\nregister\n(\nmigrations\n)\n\n\n\n/// Other services....\n\n\n\n\n\n\nRegistering the provider will add all of the services required for Fluent MySQL to work properly. It also includes a default database config struct that uses typical development environment credentials. \n\n\nYou can of course override this config struct if you have non-standard credentials.\n\n\n/// Register custom MySQL Config\n\n\nlet\n \nmysqlConfig\n \n=\n \nMySQLDatabaseConfig\n(\nhostname\n:\n \nlocalhost\n,\n \nport\n:\n \n3306\n,\n \nusername\n:\n \nvapor\n)\n\n\nservices\n.\nregister\n(\nmysqlConfig\n)\n\n\n\n\n\n\nOnce you have the \nMigrationConfig\n added, you should be able to run your application and see the following:\n\n\nMigrating mysql DB\nMigrations \ncomplete\n\nServer starting on http://localhost:8080\n\n\n\n\n\nQuery\n\n\nNow that you have created a model and a corresponding schema in your database, let's make your first query.\n\n\nrouter\n.\nget\n(\nusers\n)\n \n{\n \nreq\n \nin\n\n \nreturn\n \nUser\n.\nquery\n(\non\n:\n \nreq\n).\nall\n()\n\n\n}\n\n\n\n\n\n\nIf you run your app, and query that route, you should see an empty array returned. Now you just need to add some users! Congratulations on getting your first Fluent MySQL model and migration working.\n\n\nConnection\n\n\nWith Fluent, you always have access to the underlying database driver. Using this underlying driver to perform a query is sometimes called a \"raw query\".\n\n\nLet's take a look at a raw MySQL query.\n\n\nrouter\n.\nget\n(\nmysql-version\n)\n \n{\n \nreq\n \n-\n \nFuture\nString\n \nin\n\n \nreturn\n \nreq\n.\nwithPooledConnection\n(\nto\n:\n \n.\nmysql\n)\n \n{\n \nconn\n \nin\n\n \nreturn\n \ntry\n \nconn\n.\nquery\n(\nselect @@version as v;\n).\nmap\n(\nto\n:\n \nString\n.\nself\n)\n \n{\n \nrows\n \nin\n\n \nreturn\n \ntry\n \nrows\n[\n0\n].\nfirstValue\n(\nforColumn\n:\n \nv\n)?.\ndecode\n(\nString\n.\nself\n)\n \n??\n \nn/a\n\n \n}\n\n \n}\n\n\n}\n\n\n\n\n\n\nIn the above example, \nwithPooledConnection(to:)\n is used to create a connection to the database identified by \n.mysql\n. This is the default database identifier. See \nFluent \n Database\n to learn more.\n\n\nOnce we have the \nMySQLConnection\n, we can perform a query on it. You can learn more about the methods available in \nMySQL \n Core\n.", + "text": "Fluent MySQL\n\n\nFluent MySQL (\nvapor/fluent-mysql\n) is a type-safe, fast, and easy-to-use ORM for MySQL built on top of \nFluent\n.\n\n\n\n\nSeealso\n\n\nThe Fluent MySQL package is built on top of \nFluent\n and the pure Swift, NIO-based \nMySQL core\n. You should refer to their guides for more information about subjects not covered here.\n\n\n\n\nGetting Started\n\n\nThis section will show you how to add Fluent MySQL to your project and create your first \nMySQLModel\n.\n\n\nPackage\n\n\nThe first step to using Fluent MySQL is adding it as a dependency to your project in your SPM package manifest file.\n\n\n// swift-tools-version:4.0\n\n\nimport\n \nPackageDescription\n\n\n\nlet\n \npackage\n \n=\n \nPackage\n(\n\n \nname\n:\n \nMyApp\n,\n\n \ndependencies\n:\n \n[\n\n \n/// Any other dependencies ...\n\n\n \n// \ud83d\udd8b\ud83d\udc2c Swift ORM (queries, models, relations, etc) built on MySQL.\n\n \n.\npackage\n(\nurl\n:\n \nhttps://github.com/vapor/fluent-mysql.git\n,\n \nfrom\n:\n \n3.0.0-rc\n),\n\n \n],\n\n \ntargets\n:\n \n[\n\n \n.\ntarget\n(\nname\n:\n \nApp\n,\n \ndependencies\n:\n \n[\nFluentMySQL\n,\n \n...]),\n\n \n.\ntarget\n(\nname\n:\n \nRun\n,\n \ndependencies\n:\n \n[\nApp\n]),\n\n \n.\ntestTarget\n(\nname\n:\n \nAppTests\n,\n \ndependencies\n:\n \n[\nApp\n]),\n\n \n]\n\n\n)\n\n\n\n\n\n\nDon't forget to add the module as a dependency in the \ntargets\n array. Once you have added the dependency, regenerate your Xcode project with the following command:\n\n\nvapor xcode\n\n\n\n\n\nModel\n\n\nNow let's create our first \nMySQLModel\n. Models represent tables in your MySQL database and they are the primary method of interacting with your data. \n\n\n/// A simple user.\n\n\nfinal\n \nclass\n \nUser\n:\n \nMySQLModel\n \n{\n\n \n/// The unique identifier for this user.\n\n \nvar\n \nid\n:\n \nInt\n?\n\n\n \n/// The user\ns full name.\n\n \nvar\n \nname\n:\n \nString\n\n\n \n/// The user\ns current age in years.\n\n \nvar\n \nage\n:\n \nInt\n\n\n \n/// Creates a new user.\n\n \ninit\n(\nid\n:\n \nInt\n?\n \n=\n \nnil\n,\n \nname\n:\n \nString\n,\n \nage\n:\n \nInt\n)\n \n{\n\n \nself\n.\nid\n \n=\n \nid\n\n \nself\n.\nname\n \n=\n \nname\n\n \nself\n.\nage\n \n=\n \nage\n\n \n}\n\n\n}\n\n\n\n\n\n\nThe example above shows a \nMySQLModel\n for a simple model representing a user. You can make both \nstruct\ns and \nclass\nes a model. You can even conform types that come from external modules. The only requirement is that these types conform to \nCodable\n, which must be declared on the base type for synthesized (automatic) conformance.\n\n\nStandard practice with MySQL databases is using an auto-generated \nINTEGER\n for creating and storing unique identifiers in the \nid\n column. It's also possible to use \nUUID\ns or even \nString\ns for your identifiers. There are convenience protocol for that. \n\n\n\n\n\n\n\n\nprotocol\n\n\ntype\n\n\nkey\n\n\n\n\n\n\n\n\n\n\nMySQLModel\n\n\nInt\n\n\nid\n\n\n\n\n\n\nMySQLUUIDModel\n\n\nUUID\n\n\nid\n\n\n\n\n\n\nMySQLStringModel\n\n\nString\n\n\nid\n\n\n\n\n\n\n\n\n\n\nSeealso\n\n\nTake a look at \nFluent \n Model\n for more information on creating models with custom ID types and keys.\n\n\n\n\nMigration\n\n\nAll of your models (with some rare exceptions) should have a corresponding table\nor \nschema\nin your database. You can use a \nFluent \n Migration\n to automatically generate this schema in a testable, maintainable way. Fluent makes it easy to automatically generate a migration for your model\n\n\n\n\nTip\n\n\nIf you are creating models to represent an existing table or database, you can skip this step.\n\n\n\n\n/// Allows `User` to be used as a migration.\n\n\nextension\n \nUser\n:\n \nMigration\n \n{\n \n}\n\n\n\n\n\n\nThat's all it takes. Fluent uses Codable to analyze your model and will attempt to create the best possible schema for it.\n\n\nTake a look at \nFluent \n Migration\n if you are interested in customizing this migration.\n\n\nConfigure\n\n\nThe final step is to configure your database. At a minimum, this requires adding two things to your \nconfigure.swift\n file.\n\n\n\n\nFluentMySQLProvider\n\n\nMigrationConfig\n\n\n\n\nLet's take a look.\n\n\nimport\n \nFluentMySQL\n\n\n\n/// ...\n\n\n\n/// Register providers first\n\n\ntry\n \nservices\n.\nregister\n(\nFluentMySQLProvider\n())\n\n\n\n/// Configure migrations\n\n\nvar\n \nmigrations\n \n=\n \nMigrationConfig\n()\n\n\nmigrations\n.\nadd\n(\nmodel\n:\n \nUser\n.\nself\n,\n \ndatabase\n:\n \n.\nmysql\n)\n\n\nservices\n.\nregister\n(\nmigrations\n)\n\n\n\n/// Other services....\n\n\n\n\n\n\nRegistering the provider will add all of the services required for Fluent MySQL to work properly. It also includes a default database config struct that uses typical development environment credentials. \n\n\nYou can of course override this config struct if you have non-standard credentials.\n\n\n/// Register custom MySQL Config\n\n\nlet\n \nmysqlConfig\n \n=\n \nMySQLDatabaseConfig\n(\nhostname\n:\n \nlocalhost\n,\n \nport\n:\n \n3306\n,\n \nusername\n:\n \nvapor\n,\n \npassword\n:\n \nmypassword\n,\n \ndatabase\n:\n \nmydatabase\n)\n\n\nservices\n.\nregister\n(\nmysqlConfig\n)\n\n\n\n\n\n\nOnce you have the \nMigrationConfig\n added, you should be able to run your application and see the following:\n\n\nMigrating mysql DB\nMigrations \ncomplete\n\nServer starting on http://localhost:8080\n\n\n\n\n\nQuery\n\n\nNow that you have created a model and a corresponding schema in your database, let's make your first query.\n\n\nrouter\n.\nget\n(\nusers\n)\n \n{\n \nreq\n \nin\n\n \nreturn\n \nUser\n.\nquery\n(\non\n:\n \nreq\n).\nall\n()\n\n\n}\n\n\n\n\n\n\nIf you run your app, and query that route, you should see an empty array returned. Now you just need to add some users! Congratulations on getting your first Fluent MySQL model and migration working.\n\n\nConnection\n\n\nWith Fluent, you always have access to the underlying database driver. Using this underlying driver to perform a query is sometimes called a \"raw query\".\n\n\nLet's take a look at a raw MySQL query.\n\n\nrouter\n.\nget\n(\nmysql-version\n)\n \n{\n \nreq\n \n-\n \nFuture\nString\n \nin\n\n \nreturn\n \nreq\n.\nwithPooledConnection\n(\nto\n:\n \n.\nmysql\n)\n \n{\n \nconn\n \nin\n\n \nreturn\n \ntry\n \nconn\n.\nquery\n(\nselect @@version as v;\n).\nmap\n(\nto\n:\n \nString\n.\nself\n)\n \n{\n \nrows\n \nin\n\n \nreturn\n \ntry\n \nrows\n[\n0\n].\nfirstValue\n(\nforColumn\n:\n \nv\n)?.\ndecode\n(\nString\n.\nself\n)\n \n??\n \nn/a\n\n \n}\n\n \n}\n\n\n}\n\n\n\n\n\n\nIn the above example, \nwithPooledConnection(to:)\n is used to create a connection to the database identified by \n.mysql\n. This is the default database identifier. See \nFluent \n Database\n to learn more.\n\n\nOnce we have the \nMySQLConnection\n, we can perform a query on it. You can learn more about the methods available in \nMySQL \n Core\n.", "title": "Fluent MySQL" }, { @@ -1732,7 +1732,7 @@ }, { "location": "/mysql/fluent/#configure", - "text": "The final step is to configure your database. At a minimum, this requires adding two things to your configure.swift file. FluentMySQLProvider MigrationConfig Let's take a look. import FluentMySQL /// ... /// Register providers first try services . register ( FluentMySQLProvider ()) /// Configure migrations var migrations = MigrationConfig () migrations . add ( model : User . self , database : . mysql ) services . register ( migrations ) /// Other services.... Registering the provider will add all of the services required for Fluent MySQL to work properly. It also includes a default database config struct that uses typical development environment credentials. You can of course override this config struct if you have non-standard credentials. /// Register custom MySQL Config let mysqlConfig = MySQLDatabaseConfig ( hostname : localhost , port : 3306 , username : vapor ) services . register ( mysqlConfig ) Once you have the MigrationConfig added, you should be able to run your application and see the following: Migrating mysql DB\nMigrations complete \nServer starting on http://localhost:8080", + "text": "The final step is to configure your database. At a minimum, this requires adding two things to your configure.swift file. FluentMySQLProvider MigrationConfig Let's take a look. import FluentMySQL /// ... /// Register providers first try services . register ( FluentMySQLProvider ()) /// Configure migrations var migrations = MigrationConfig () migrations . add ( model : User . self , database : . mysql ) services . register ( migrations ) /// Other services.... Registering the provider will add all of the services required for Fluent MySQL to work properly. It also includes a default database config struct that uses typical development environment credentials. You can of course override this config struct if you have non-standard credentials. /// Register custom MySQL Config let mysqlConfig = MySQLDatabaseConfig ( hostname : localhost , port : 3306 , username : vapor , password : mypassword , database : mydatabase ) services . register ( mysqlConfig ) Once you have the MigrationConfig added, you should be able to run your application and see the following: Migrating mysql DB\nMigrations complete \nServer starting on http://localhost:8080", "title": "Configure" }, { diff --git a/build/3.0/sitemap.xml b/build/3.0/sitemap.xml index 11205081..68fbfc2b 100644 --- a/build/3.0/sitemap.xml +++ b/build/3.0/sitemap.xml @@ -4,7 +4,7 @@ / - 2018-05-10 + 2018-05-22 daily @@ -13,13 +13,13 @@ /install/macos/ - 2018-05-10 + 2018-05-22 daily /install/ubuntu/ - 2018-05-10 + 2018-05-22 daily @@ -29,73 +29,73 @@ /getting-started/hello-world/ - 2018-05-10 + 2018-05-22 daily /getting-started/toolbox/ - 2018-05-10 + 2018-05-22 daily /getting-started/spm/ - 2018-05-10 + 2018-05-22 daily /getting-started/xcode/ - 2018-05-10 + 2018-05-22 daily /getting-started/structure/ - 2018-05-10 + 2018-05-22 daily /getting-started/application/ - 2018-05-10 + 2018-05-22 daily /getting-started/controllers/ - 2018-05-10 + 2018-05-22 daily /getting-started/routing/ - 2018-05-10 + 2018-05-22 daily /getting-started/content/ - 2018-05-10 + 2018-05-22 daily /getting-started/async/ - 2018-05-10 + 2018-05-22 daily /getting-started/services/ - 2018-05-10 + 2018-05-22 daily /getting-started/cloud/ - 2018-05-10 + 2018-05-22 daily @@ -105,13 +105,13 @@ /async/getting-started/ - 2018-05-10 + 2018-05-22 daily /async/overview/ - 2018-05-10 + 2018-05-22 daily @@ -121,13 +121,13 @@ /console/getting-started/ - 2018-05-10 + 2018-05-22 daily /console/overview/ - 2018-05-10 + 2018-05-22 daily @@ -137,13 +137,13 @@ /command/getting-started/ - 2018-05-10 + 2018-05-22 daily /command/overview/ - 2018-05-10 + 2018-05-22 daily @@ -153,13 +153,13 @@ /core/getting-started/ - 2018-05-10 + 2018-05-22 daily /core/overview/ - 2018-05-10 + 2018-05-22 daily @@ -169,31 +169,31 @@ /crypto/getting-started/ - 2018-05-10 + 2018-05-22 daily /crypto/digests/ - 2018-05-10 + 2018-05-22 daily /crypto/ciphers/ - 2018-05-10 + 2018-05-22 daily /crypto/asymmetric/ - 2018-05-10 + 2018-05-22 daily /crypto/random/ - 2018-05-10 + 2018-05-22 daily @@ -203,13 +203,13 @@ /database-kit/getting-started/ - 2018-05-10 + 2018-05-22 daily /database-kit/overview/ - 2018-05-10 + 2018-05-22 daily @@ -219,61 +219,61 @@ /fluent/getting-started/ - 2018-05-10 + 2018-05-22 daily /fluent/models/ - 2018-05-10 + 2018-05-22 daily /fluent/migrations/ - 2018-05-10 + 2018-05-22 daily /fluent/querying/ - 2018-05-10 + 2018-05-22 daily /fluent/query-builder/ - 2018-05-10 + 2018-05-22 daily /fluent/schema-builder/ - 2018-05-10 + 2018-05-22 daily /fluent/relations/ - 2018-05-10 + 2018-05-22 daily /fluent/pivot/ - 2018-05-10 + 2018-05-22 daily /fluent/transaction/ - 2018-05-10 + 2018-05-22 daily /fluent/database/ - 2018-05-10 + 2018-05-22 daily @@ -283,25 +283,25 @@ /http/getting-started/ - 2018-05-10 + 2018-05-22 daily /http/client/ - 2018-05-10 + 2018-05-22 daily /http/server/ - 2018-05-10 + 2018-05-22 daily /http/message/ - 2018-05-10 + 2018-05-22 daily @@ -311,19 +311,19 @@ /leaf/getting-started/ - 2018-05-10 + 2018-05-22 daily /leaf/basics/ - 2018-05-10 + 2018-05-22 daily /leaf/custom-tags/ - 2018-05-10 + 2018-05-22 daily @@ -333,13 +333,13 @@ /logging/getting-started/ - 2018-05-10 + 2018-05-22 daily /logging/overview/ - 2018-05-10 + 2018-05-22 daily @@ -349,13 +349,13 @@ /multipart/getting-started/ - 2018-05-10 + 2018-05-22 daily /multipart/overview/ - 2018-05-10 + 2018-05-22 daily @@ -365,19 +365,19 @@ /mysql/getting-started/ - 2018-05-10 + 2018-05-22 daily /mysql/fluent/ - 2018-05-10 + 2018-05-22 daily /mysql/core/ - 2018-05-10 + 2018-05-22 daily @@ -387,19 +387,19 @@ /postgresql/getting-started/ - 2018-05-10 + 2018-05-22 daily /postgresql/fluent/ - 2018-05-10 + 2018-05-22 daily /postgresql/core/ - 2018-05-10 + 2018-05-22 daily @@ -409,31 +409,31 @@ /redis/getting-started/ - 2018-05-10 + 2018-05-22 daily /redis/basics/ - 2018-05-10 + 2018-05-22 daily /redis/custom-commands/ - 2018-05-10 + 2018-05-22 daily /redis/pub-sub/ - 2018-05-10 + 2018-05-22 daily /redis/pipeline/ - 2018-05-10 + 2018-05-22 daily @@ -443,13 +443,13 @@ /routing/getting-started/ - 2018-05-10 + 2018-05-22 daily /routing/overview/ - 2018-05-10 + 2018-05-22 daily @@ -459,19 +459,19 @@ /service/getting-started/ - 2018-05-10 + 2018-05-22 daily /service/services/ - 2018-05-10 + 2018-05-22 daily /service/provider/ - 2018-05-10 + 2018-05-22 daily @@ -481,13 +481,13 @@ /sql/getting-started/ - 2018-05-10 + 2018-05-22 daily /sql/overview/ - 2018-05-10 + 2018-05-22 daily @@ -497,19 +497,19 @@ /sqlite/getting-started/ - 2018-05-10 + 2018-05-22 daily /sqlite/fluent/ - 2018-05-10 + 2018-05-22 daily /sqlite/core/ - 2018-05-10 + 2018-05-22 daily @@ -519,7 +519,7 @@ /template-kit/getting-started/ - 2018-05-10 + 2018-05-22 daily @@ -529,7 +529,7 @@ /testing/getting-started/ - 2018-05-10 + 2018-05-22 daily @@ -539,13 +539,13 @@ /url-encoded-form/getting-started/ - 2018-05-10 + 2018-05-22 daily /url-encoded-form/overview/ - 2018-05-10 + 2018-05-22 daily @@ -555,13 +555,13 @@ /validation/getting-started/ - 2018-05-10 + 2018-05-22 daily /validation/overview/ - 2018-05-10 + 2018-05-22 daily @@ -571,31 +571,31 @@ /vapor/getting-started/ - 2018-05-10 + 2018-05-22 daily /vapor/client/ - 2018-05-10 + 2018-05-22 daily /vapor/content/ - 2018-05-10 + 2018-05-22 daily /vapor/sessions/ - 2018-05-10 + 2018-05-22 daily /vapor/websocket/ - 2018-05-10 + 2018-05-22 daily @@ -605,13 +605,13 @@ /websocket/getting-started/ - 2018-05-10 + 2018-05-22 daily /websocket/overview/ - 2018-05-10 + 2018-05-22 daily @@ -621,31 +621,31 @@ /version/1_5/ - 2018-05-10 + 2018-05-22 daily /version/2_0/ - 2018-05-10 + 2018-05-22 daily /version/3_0/ - 2018-05-10 + 2018-05-22 daily /version/upgrading/ - 2018-05-10 + 2018-05-22 daily /version/support/ - 2018-05-10 + 2018-05-22 daily