mirror of https://github.com/vapor/docs.git
Merge pull request #1 from vapor/master
merge from vapor original repo.
This commit is contained in:
commit
e71d400919
|
|
@ -14,6 +14,10 @@ Read this in [正體中文](https://github.com/vapor/documentation/blob/master/R
|
|||
|
||||
You can read this guide by clicking through the folders and markdown files on [GitHub](https://github.com/vapor/documentation) or through the rendered [GitHub Pages](https://vapor.github.io/documentation/).
|
||||
|
||||
## API
|
||||
|
||||
Auto-generated API documentation is located at [api.vapor.codes](http://api.vapor.codes).
|
||||
|
||||
## Packages
|
||||
|
||||
Here are a list of all the packages and modules included with Vapor (also useable individually).
|
||||
|
|
@ -36,7 +40,7 @@ Here are a list of all the packages and modules included with Vapor (also useabl
|
|||
- [Crypto](https://github.com/vapor/crypto): Cryptography from LibreSSL and Swift.
|
||||
- Digests: Hashing with and without authentication.
|
||||
- Ciphers: Encryption and decryption
|
||||
- Random: Psuedo and cryptographically secure randomness.
|
||||
- Random: Pseudo and cryptographically secure randomness.
|
||||
- BCrypt: Pure Swift implementation.
|
||||
- [Node](https://github.com/vapor/node): Data structure for easy type conversions.
|
||||
- [Polymorphic](https://github.com/vapor/polymorphic): Syntax for easily accessing values from common types like JSON.
|
||||
|
|
@ -70,6 +74,9 @@ Here are a list of providers and third party packages that work great with Vapor
|
|||
- [VaporS3Signer](https://github.com/JustinM1/VaporS3Signer): Generate V4 Auth Header/Pre-Signed URL for AWS S3 REST API
|
||||
- [Flock](https://github.com/jakeheis/Flock): Automated deployment of Swift projects to servers
|
||||
- [VaporFlock](https://github.com/jakeheis/VaporFlock): Use Flock to deploy Vapor applications
|
||||
- [VaporForms](https://github.com/bygri/vapor-forms): Brings simple, dynamic and re-usable web form handling to Vapor.
|
||||
- [Jobs](https://github.com/BrettRToomey/Jobs): A minimalistic job/background-task system for Swift.
|
||||
- [Heimdall](https://github.com/himani93/heimdall): An easy to use HTTP request logger.
|
||||
|
||||
|
||||
## Authors
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ Vapor 是一個在 Swift 上很受歡迎的 Web framework。它提供了清楚
|
|||
- [VaporS3Signer](https://github.com/JustinM1/VaporS3Signer): 用來產生 HTTP request 的 headers 及已經簽證過的 URL,用來 request AWS S3 的 REST API。
|
||||
- [Flock](https://github.com/jakeheis/Flock): 自動將 Swift 專案發佈上主機。
|
||||
- [VaporFlock](https://github.com/jakeheis/VaporFlock): 利用 Flock 發佈 Vapor applications。
|
||||
- [VaporForms](https://github.com/bygri/vapor-forms)。
|
||||
- [Jobs](https://github.com/BrettRToomey/Jobs)。
|
||||
|
||||
|
||||
## 作者們
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ The `--env=production` flag will disable verbose logging and prioritize the `Con
|
|||
|
||||
### Environment
|
||||
|
||||
You can export variables to your Vapor app with sueprvisor.
|
||||
You can export variables to your Vapor app with supervisor.
|
||||
|
||||
```sh
|
||||
environment=PORT=8123
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ This graphic shows the relation between Drivers and Providers using MySQL as an
|
|||
If you want to use Fluent without Vapor, you will import Drivers into your package. If you are using Vapor, you will import Providers.
|
||||
|
||||
Search GitHub for:
|
||||
- [Fluent Drivers](https://github.com/vapor?utf8=✓&query=-driver)
|
||||
- [Vapor Providers](https://github.com/vapor?utf8=✓&query=-provider)
|
||||
- [Fluent Drivers](https://github.com/vapor?utf8=✓&q=-driver)
|
||||
- [Vapor Providers](https://github.com/vapor?utf8=✓&q=-provider)
|
||||
|
||||
Not all drivers have providers yet, and not all drivers or providers are up to date with the latest Vapor 1.0. This is a great way to contribute!
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ import PackageDescription
|
|||
let package = Package(
|
||||
name: "Hello",
|
||||
dependencies: [
|
||||
.Package(url: "https://github.com/vapor/vapor.git", majorVersion: 1, minor: 0)
|
||||
.Package(url: "https://github.com/vapor/vapor.git", majorVersion: 1, minor: 1)
|
||||
]
|
||||
)
|
||||
```
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ Let's add a custom key to the `servers.json` file:
|
|||
This can be accessed from your application's config using the following.
|
||||
|
||||
```swift
|
||||
let customValue = app.config["server", "http", "custom-key"].string
|
||||
let customValue = drop.config["server", "http", "custom-key"]?.string ?? "default"
|
||||
```
|
||||
|
||||
That's it, feel free to add and utilize keys as necessary to make your application configuration easier.
|
||||
|
|
@ -71,13 +71,13 @@ You can access your config directory with the following syntax. `app.config[<#fi
|
|||
We can access this file by making sure the first argument in our subscript is keys. To get the first name in our list:
|
||||
|
||||
```swift
|
||||
let name = app.config["keys", "test-names", 0].string
|
||||
let name = drop.config["keys", "test-names", 0]?.string ?? "default"
|
||||
```
|
||||
|
||||
Or our mongo url:
|
||||
|
||||
```swift
|
||||
let mongoUrl = app.config["keys", "mongo", "url"].string
|
||||
let mongoUrl = drop.config["keys", "mongo", "url"].?string ?? "default"
|
||||
```
|
||||
|
||||
## Advanced Configurations
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ The `Droplet` will continue to use the default logger until you modify the `Conf
|
|||
|
||||
The `Droplet` init method is fairly simple since most properties are variable and can be changed after initialization.
|
||||
|
||||
Most plugins for Vapor come with a [Provider](providers.md), these take care of configuration details for you.
|
||||
Most plugins for Vapor come with a [Provider](provider.md), these take care of configuration details for you.
|
||||
|
||||
```swift
|
||||
Droplet(
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@ To specifically target JSON, use the `request.json` property.
|
|||
|
||||
```swift
|
||||
drop.post("json") { request in
|
||||
guard let name = request.json["name"].string else {
|
||||
throw Abort.badRequest
|
||||
}
|
||||
guard let name = request.json?["name"]?.string else {
|
||||
throw Abort.badRequest
|
||||
}
|
||||
|
||||
return "Hello, \(name)!"
|
||||
return "Hello, \(name)!"
|
||||
}
|
||||
```
|
||||
The above snippet will only work if the request is sent with JSON data.
|
||||
|
|
|
|||
209
guide/leaf.md
209
guide/leaf.md
|
|
@ -4,7 +4,7 @@ currentMenu: guide-leaf
|
|||
|
||||
# Leaf
|
||||
|
||||
Welcome to Leaf. Leaf's goal is to be a simple templating language that can make generating views easier. There's a lot of great templating languages, use what's best for you, maybe that's leaf! The goals of leaf are as follows:
|
||||
Welcome to Leaf. Leaf's goal is to be a simple templating language that can make generating views easier. There's a lot of great templating languages, use what's best for you, maybe that's Leaf! The goals of Leaf are as follows:
|
||||
|
||||
- Small set of strictly enforced rules
|
||||
- Consistency
|
||||
|
|
@ -12,78 +12,88 @@ Welcome to Leaf. Leaf's goal is to be a simple templating language that can make
|
|||
- Extensibility
|
||||
|
||||
## Syntax
|
||||
|
||||
Leaf syntax is based around a single token, in this case, the hashtag: `#`.
|
||||
|
||||
>It's important to note that _all_ hashtags will be parsed, there is no escaping. Use `#()` to render a plain `#`. `#()Leaf` => `#Leaf`. Or, for larger sections, use the `raw` tag. `#raw() { #Do #whatever #you #want #to #in #here!. }`
|
||||
|
||||
### Structure
|
||||
|
||||
Here we see all the components of a Leaf tag.
|
||||
Leaf Tags are made up of 4 Elements:
|
||||
- Token: `#` is the Token
|
||||
- Name: A `string` that identifies the tag
|
||||
- Parameter List: `()` May accept 0 or more arguments
|
||||
- Body(optional): `{}` Must be separated from the Parameter List by a space
|
||||
|
||||
```leaf
|
||||
#someTag(parameter.list, goes, "here") {
|
||||
This is an optional body here
|
||||
}
|
||||
There can be many different usages of these 4 elements depending on the Tag's implementation. Let's look at a few examples of how Leaf's built-in Tags might be used:
|
||||
|
||||
- `#()`
|
||||
- `#(variable)`
|
||||
- `#import("template")`
|
||||
- `#export("link") { <a href="#()"></a> }`
|
||||
- `#index(friends, "0")`
|
||||
- `#loop(friends, "friend") { <li>#(friend.name)</li> }`
|
||||
- `#raw() { <a href="#raw">Anything goes!@#$%^&*</a> }`
|
||||
|
||||
### Using the `#` token in HTML
|
||||
|
||||
The token cannot be escaped. Use the `#()` or `#raw() {}` Tag to output a `#` in a Leaf Template. `#()` => `#`
|
||||
|
||||
### Raw HTML
|
||||
|
||||
All Leaf output is escaped by default. Use the `#raw() {}` Tag for unescaped output.
|
||||
`#raw() { <a href="#link">Link</a> }` => `<a href="#link">Link</a>`
|
||||
> IMPORTANT! Make sure you are not using the `#raw() {}` Tag with user input.
|
||||
|
||||
### Chaining
|
||||
|
||||
The double token: `##` indicates a chain. It can be applied to any standard Tag. If the previous Tag fails, the chained Tag will be given an opportunity to run.
|
||||
|
||||
```
|
||||
#if(hasFriends) ##embed("getFriends")
|
||||
```
|
||||
|
||||
##### Token
|
||||
### Leaf's built-in Tags
|
||||
|
||||
>The `#` token will define we're a tag
|
||||
#### Token: `#()`
|
||||
|
||||
##### Name
|
||||
```
|
||||
#() #()hashtags #()FTW => # #Hashtags #FTW
|
||||
```
|
||||
|
||||
>In above example, it would be `someTag`. While not strictly enforced, it is **highly** encouraged that users only use alphanumeric characters in names. This may be enforced in future versions.
|
||||
#### Raw: `#raw() {}`
|
||||
|
||||
##### Parameter List
|
||||
|
||||
`Var(parameter, list), Var(goes), Const("here")`
|
||||
|
||||
##### Body
|
||||
|
||||
> This is an optional body here indicated w/ open and closed curly brackets.
|
||||
|
||||
#### Using # in html with Leaf
|
||||
|
||||
If you need # to appear alone in your html, simply using `#()` will render as #. Alternatively, the raw tag is available for larger sections of code:
|
||||
|
||||
```leaf
|
||||
```
|
||||
#raw() {
|
||||
Do whatever w/ #'s here, this code
|
||||
won't be rendered as leaf document.
|
||||
It's a great place for things like Javascript or large HTML sections.
|
||||
Do whatever w/ #'s here, this code won't be rendered as leaf document and is not escaped.
|
||||
It's a great place for things like Javascript or large HTML sections.
|
||||
}
|
||||
```
|
||||
|
||||
## Syntax Highlighting
|
||||
#### Equal: `#equal(lhs, rhs) {}`
|
||||
|
||||
### Atom
|
||||
```
|
||||
#equal(leaf, leaf) { Leaf == Leaf } => Leaf == Leaf
|
||||
#equal(leaf, mustache) { Leaf == Mustache } =>
|
||||
```
|
||||
|
||||
[language-leaf](https://atom.io/packages/language-leaf) by ButkiewiczP
|
||||
#### Variable: `#(variable)`
|
||||
|
||||
## Examples
|
||||
|
||||
#### Variable
|
||||
|
||||
Variables are added w/ just a number sign.
|
||||
|
||||
```leaf
|
||||
```
|
||||
Hello, #(name)!
|
||||
```
|
||||
|
||||
#### Loop
|
||||
#### Loop: `#loop(object, "index")`
|
||||
|
||||
Loop a variable
|
||||
|
||||
```leaf
|
||||
```
|
||||
#loop(friends, "friend") {
|
||||
Hello, #(friend.name)!
|
||||
}
|
||||
```
|
||||
#### Index: `#loop(object, "index")`
|
||||
|
||||
#### If - Else
|
||||
```
|
||||
Hello, #index(friends, "0")!
|
||||
```
|
||||
|
||||
```leaf
|
||||
#### If - Else: `#if(bool) ##else() { this }`
|
||||
|
||||
```
|
||||
#if(entering) {
|
||||
Hello, there!
|
||||
} ##if(leaving) {
|
||||
|
|
@ -93,21 +103,14 @@ Loop a variable
|
|||
}
|
||||
```
|
||||
|
||||
#### Chaining
|
||||
#### Import: `#import("template")`
|
||||
#### Export: `#export("template") { Leaf/HTML }`
|
||||
#### Extend: `#extend("template")`
|
||||
#### Embed: `#embed("template")`
|
||||
|
||||
The double token, `##` indicates a chain. If the previous tag fails, this tag will be given an opportunity to run. It can be applied to any standard tag, for example, above we chain to else, but we could also chain to loops.
|
||||
> When using these Layout Tags, omit the template file's .leaf extension.
|
||||
|
||||
```
|
||||
#empty(friends) {
|
||||
Try adding some friends!
|
||||
} ##loop(friends, "friend") {
|
||||
<li> #(friend.name) </li>
|
||||
}
|
||||
```
|
||||
|
||||
#### Extending
|
||||
|
||||
```swift
|
||||
/// base.leaf
|
||||
<!DOCTYPE html>
|
||||
#import("html")
|
||||
|
|
@ -115,38 +118,15 @@ The double token, `##` indicates a chain. If the previous tag fails, this tag wi
|
|||
/// html.leaf
|
||||
#extend("base")
|
||||
|
||||
#export("html") {
|
||||
<html></html>
|
||||
}
|
||||
```
|
||||
|
||||
Leaf renders `html.leaf` as:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html></html>
|
||||
```
|
||||
|
||||
#### Embedding
|
||||
|
||||
```swift
|
||||
/// base.leaf
|
||||
<!DOCTYPE html>
|
||||
#import("html")
|
||||
|
||||
/// html.leaf
|
||||
#extend("base")
|
||||
|
||||
#export("html") {
|
||||
<html>#embed("body")</html>
|
||||
}
|
||||
#export("html") { <html>#embed("body")</html> }
|
||||
|
||||
/// body.leaf
|
||||
<body></body>
|
||||
```
|
||||
|
||||
Leaf renders `html.leaf` as:
|
||||
|
||||
```html
|
||||
```
|
||||
<!DOCTYPE html>
|
||||
<html><body></body></html>
|
||||
```
|
||||
|
|
@ -155,40 +135,45 @@ Leaf renders `html.leaf` as:
|
|||
|
||||
Look at the existing tags for advanced scenarios, let's look at a basic example by creating `Index` together. This tag will take two arguments, an array, and an index to access.
|
||||
|
||||
```
|
||||
```swift
|
||||
class Index: BasicTag {
|
||||
let name = "index"
|
||||
let name = "index"
|
||||
|
||||
func run(arguments: [Argument]) throws -> Node? {
|
||||
guard
|
||||
arguments.count == 2,
|
||||
let array = arguments[0].value?.nodeArray,
|
||||
let index = arguments[1].value?.int,
|
||||
index < array.count
|
||||
else { return nil }
|
||||
func run(arguments: [Argument]) throws -> Node? {
|
||||
guard
|
||||
arguments.count == 2,
|
||||
let array = arguments[0].value?.nodeArray,
|
||||
let index = arguments[1].value?.int,
|
||||
index < array.count
|
||||
else { return nil }
|
||||
return array[index]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Now, after creating our `Stem`, we can register the tag:
|
||||
We can now register this Tag in our `main.swift` file with:
|
||||
|
||||
```
|
||||
stem.register(Index())
|
||||
```
|
||||
|
||||
And use it like so:
|
||||
|
||||
```
|
||||
Hello, #index(friends, "0")!
|
||||
```
|
||||
|
||||
We can also chain `else` to this like we did earlier if we want to check existence first:
|
||||
|
||||
```
|
||||
#index(friends, "0") {
|
||||
Hello, #(self)!
|
||||
} ##else() {
|
||||
Nobody's there!
|
||||
```swift
|
||||
if let leaf = drop.view as? LeafRenderer {
|
||||
leaf.stem.register(Version())
|
||||
}
|
||||
```
|
||||
|
||||
And use it just like we did [above](#index).
|
||||
|
||||
> Note: Use of non-alphanumeric characters in Tag Names is **strongly discouraged** and may be disallowed in future versions of Leaf.
|
||||
|
||||
## Syntax Highlighting
|
||||
|
||||
### Atom
|
||||
|
||||
[language-leaf](https://atom.io/packages/language-leaf) by ButkiewiczP
|
||||
|
||||
### Xcode
|
||||
It is not currently possible to implement Leaf Syntax Highlighting in Xcode, however, using Xcode's HTML Syntax Coloring can help a bit. Select one or more Leaf files and then choose Editor > Syntax Coloring > HTML. Your selected Leaf files will now use Xcode's HTML Syntax Coloring. Unfortunately the usefulness of this is limited because this association will be removed when `vapor xcode` is run.
|
||||
|
||||
There appears to be a way to [make Xcode file associations persist](http://stackoverflow.com/questions/9050035/how-to-make-xcode-recognize-a-custom-file-extension-as-objective-c-for-syntax-hi) but that requires a bit more kung-fu.
|
||||
|
||||
### CLion & AppCode
|
||||
|
||||
Some preliminary work has been done to implement a Leaf Plugin for CLion & AppCode but lack of skill and interest in Java has slowed progress! If you have IntelliJ SDK experience and want to help with this, message Tom Holland on [Vapor Slack](http://vapor.team)
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ enum FooError: Error {
|
|||
}
|
||||
```
|
||||
|
||||
Say there is a custom error that either you defined or one of the APIs you are using `throw`s. This error must be caught when thrown, or else it will end up as a server error which may be unexpected to a user. The most obvious solution is to catch the error in the route closure.
|
||||
Say there is a custom error that either you defined or one of the APIs you are using `throws`. This error must be caught when thrown, or else it will end up as a server error which may be unexpected to a user. The most obvious solution is to catch the error in the route closure.
|
||||
|
||||
```swift
|
||||
app.get("foo") { request in
|
||||
|
|
@ -180,14 +180,14 @@ Middleware pairs great with request/response extensions and storage.
|
|||
final class PokemonMiddleware: Middleware {
|
||||
let drop: Droplet
|
||||
init(drop: Droplet) {
|
||||
self.drop = dropt
|
||||
self.drop = drop
|
||||
}
|
||||
|
||||
func respond(to request: Request, chainingTo next: Responder) throws -> Response {
|
||||
let response = try next.respond(to: request)
|
||||
|
||||
if let pokemon = response.pokemon {
|
||||
request.accept.prefers("html") {
|
||||
if request.accept.prefers("html") {
|
||||
response.view = try drop.view("pokemon.mustache", context: pokemon)
|
||||
} else {
|
||||
response.json = try pokemon.makeJSON()
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Adding a provider to your application takes 2-3 steps.
|
|||
|
||||
### Add Package
|
||||
|
||||
All of Vapor's providers end with the `-provider` syntax. You can see a list of [available providers](https://github.com/vapor?utf8=✓&query=-provider) by searching on our GitHub.
|
||||
All of Vapor's providers end with the `-provider` syntax. You can see a list of [available providers](https://github.com/vapor?utf8=✓&q=-provider) by searching on our GitHub.
|
||||
|
||||
To add the provider to your package, add it as a dependency in your `Package.swift` file.
|
||||
|
||||
|
|
@ -74,8 +74,8 @@ import VaporMySQL
|
|||
|
||||
let drop = Droplet()
|
||||
|
||||
let mysql = VaporMySQL.Provider(host: "localhost", user: "root")
|
||||
try drop.addProvider(mysql)
|
||||
let mysql = try VaporMySQL.Provider(host: "localhost", user: "root", password: "", database: "vapor")
|
||||
drop.addProvider(mysql)
|
||||
|
||||
...
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ This creates a route that matches `users/:id` where the `:id` is an `Int`. Here'
|
|||
|
||||
```swift
|
||||
drop.get("users", ":id") { request in
|
||||
guard let userId = request.parameters["id"].int else {
|
||||
guard let userId = request.parameters["id"]?.int else {
|
||||
throw Abort.badRequest
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ The resulting path for the above example is `/v1/users/:userId/posts/:postId`. I
|
|||
As shown briefly above, you are still free to do traditional routing. This can be useful for especially complex situations.
|
||||
|
||||
```swift
|
||||
drop.get("v1", "users", ":userId", "posts", ":postId", "comments": ":commentId") { request in
|
||||
drop.get("v1", "users", ":userId", "posts", ":postId", "comments", ":commentId") { request in
|
||||
let userId = try request.parameters.extract("userId") as Int
|
||||
let postId = try request.parameters.extract("postId") as Int
|
||||
let commentId = try request.parameters.extract("commentId") as Int
|
||||
|
|
|
|||
|
|
@ -69,6 +69,46 @@
|
|||
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
|
||||
<script src="{{ baseUrl}}/scripts/highlight.pack.js"></script>
|
||||
|
||||
<script>
|
||||
hljs.registerLanguage("leaf", function (hljs) {
|
||||
/* Author: Hale Chan <halechan@qq.com> */
|
||||
return {
|
||||
c: [
|
||||
{
|
||||
cN: 'function',
|
||||
b: '#+',
|
||||
e: '[)] ',
|
||||
rB: true,
|
||||
eE: false,
|
||||
c : [
|
||||
{
|
||||
b: '[(]',
|
||||
e: '[)]',
|
||||
eE: true,
|
||||
c: [
|
||||
{
|
||||
cN: 'string',
|
||||
b: '"',
|
||||
e: '"'
|
||||
},
|
||||
{
|
||||
cN: 'title',
|
||||
b: '[A-Za-z_][A-Za-z_0-9]*'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
cN: 'keyword',
|
||||
b: '#+([A-Za-z$_][0-9A-Za-z$_]*)?',
|
||||
eP: true
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
// Syntax highlighting
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -48,7 +48,7 @@ drop.run()
|
|||
The first thing we'll do is in my testing target, add a file called `Droplet+Test.swift`. It will look like this:
|
||||
|
||||
```swift
|
||||
import Vapor
|
||||
@testable import Vapor
|
||||
|
||||
func makeTestDroplet() throws -> Droplet {
|
||||
let drop = Droplet(arguments: ["dummy/path/", "prepare"], ...)
|
||||
|
|
@ -58,7 +58,7 @@ func makeTestDroplet() throws -> Droplet {
|
|||
}
|
||||
```
|
||||
|
||||
This looks a lot like our initializer in `main.swift`, but there are 2 very key differences.
|
||||
This looks a lot like our initializer in `main.swift`, but there are 3 very key differences.
|
||||
|
||||
### Droplet(arguments: ["dummy/path/", "prepare"], ...
|
||||
|
||||
|
|
@ -68,6 +68,10 @@ The `arguments:` parameter in our `Droplet` creation. This is rarely used except
|
|||
|
||||
You'll notice here that we're calling `runCommands()` instead of `run()`. This allows the `Droplet` to do all the setup it would normally do before booting without actually binding to a socket or exiting.
|
||||
|
||||
### `@testable import Vapor`
|
||||
|
||||
We'll need to import the testable compilation of Vapor to access the `runCommands` function. This is currently not public as a protection against accidental bugs in live apps.
|
||||
|
||||
## Test Our Droplet
|
||||
|
||||
Now that all of this has been created, we're ready to start testing our application's `Droplet`. Here's how a really basic test might look:
|
||||
|
|
|
|||
Loading…
Reference in New Issue