From d470256b0fc067c1a8b1868ba6bbc7a41a38f7bc Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Thu, 5 Oct 2017 13:14:58 +0200 Subject: [PATCH 1/4] Added examples --- README.md | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) diff --git a/README.md b/README.md index 0641f04..f2bb7d4 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,36 @@ This collection of templates is related to models and automating their conversio ## Model Automatically generates an initializer and an enum for MySQL enum types. +Example: +```swift +final class User: Model { + var name: String + var age: Int? +} +``` + +Becomes: +```swift +// sourcery: model +final class User: Model { + var name: String + var age: Int? + +// sourcery:inline:auto:User.Models + let storage = Storage() + + + internal init( + name: String, + age: Int? = nil + ) { + self.name = name + self.age = age + } +// sourcery:end +} +``` + | Key | Description | | ----------- | -----------------------------------------------------------------------| | `enumName` | Generate a Swift enum for MySQL with accessors for a list of all cases.| @@ -17,6 +47,43 @@ Automatically generates an initializer and an enum for MySQL enum types. ## Preparation Generates a list of database keys, automates `prepare` and `revert` functions. +Example: +```swift +final class User: Model { + var name: String + var age: Int? +} +``` + +Becomes: +```swift +import Vapor +import Fluent + +extension User: Preparation { + internal enum DatabaseKeys { + static let id = User.idKey + static let name = "name" + static let age = "age" + } + + // MARK: - Preparations (User) + internal static func prepare(_ database: Database) throws { + try database.create(self) { + $0.id() + $0.string(DatabaseKeys.name) + $0.int(DatabaseKeys.age, optional: true) + } + + } + + internal static func revert(_ database: Database) throws { + try database.delete(self) + } +} + +``` + | Key | Description | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------| | `databaseKey` | Set the database key (default is the name of the member). | @@ -34,6 +101,39 @@ Generates a list of database keys, automates `prepare` and `revert` functions. ## RowConvertible Automates `init (row: Row)` and `makeRow` boilerplate. +Example: +```swift +final class User: Model { + var name: String + var age: Int? +} +``` + +Becomes: +```swift +import Vapor +import Fluent + +extension User: RowConvertible { + // MARK: - RowConvertible (User) + convenience internal init (row: Row) throws { + try self.init( + name: row.get(DatabaseKeys.name), + age: row.get(DatabaseKeys.age) + ) + } + + internal func makeRow() throws -> Row { + var row = Row() + + try row.set(DatabaseKeys.name, name) + try row.set(DatabaseKeys.age, age) + + return row + } +} +``` + | Key | Description | | ---------------------- | --------------------------------------------------------------------------------- | | `databaseKey` | Set the database key (default is the name of the member). | @@ -43,6 +143,38 @@ Automates `init (row: Row)` and `makeRow` boilerplate. ## NodeRepresentable Generates a list of node keys and `makeNode(in context: Context?)`. +Example: +```swift +final class User: Model { + var name: String + var age: Int? +} +``` + +Becomes: +```swift +import Vapor +import Fluent + +extension User: NodeRepresentable { + internal enum NodeKeys: String { + case name + case age + } + + // MARK: - NodeRepresentable (User) + func makeNode(in context: Context?) throws -> Node { + var node = Node([:]) + + try node.set(User.idKey, id) + try node.set(NodeKeys.name.rawValue, name) + try node.set(NodeKeys.age.rawValue, age) + + return node + } +} +``` + | Key | Description | | ------------------------- | ------------------------------------------------------------------------------------| | `nodeKey` | Set the key for node (de)serialization. | @@ -52,6 +184,44 @@ Generates a list of node keys and `makeNode(in context: Context?)`. ## JSONConvertible Generates a list of JSON keys, `init(json: JSON)` and `makeJSON`. +Example: +```swift +final class User: Model { + var name: String + var age: Int? +} +``` + +Becomes: +```swift +extension User: JSONConvertible { + internal enum JSONKeys: String { + case name + case age + } + + // MARK: - JSONConvertible (User) + internal convenience init(json: JSON) throws { + try self.init( + name: json.get(JSONKeys.name.rawValue), + age: json.get(JSONKeys.age.rawValue) + ) + } + + internal func makeJSON() throws -> JSON { + var json = JSON() + + try json.set(User.idKey, id) + try json.set(JSONKeys.name.rawValue, name) + try json.set(JSONKeys.age.rawValue, age) + + return json + } +} + +extension User: ResponseRepresentable {} +``` + | Key | Description | | ----------------------- | ----------------------------------------------------------------------------------| | `jsonValue` | Set the value for JSON serialization. | From 3ee9674a709e258d4bb71b2915c248942993a81f Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Thu, 5 Oct 2017 13:17:25 +0200 Subject: [PATCH 2/4] Added annotations titles --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index f2bb7d4..61f1e40 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ final class User: Model { } ``` +#### Annotations + | Key | Description | | ----------- | -----------------------------------------------------------------------| | `enumName` | Generate a Swift enum for MySQL with accessors for a list of all cases.| @@ -84,6 +86,8 @@ extension User: Preparation { ``` +#### Annotations + | Key | Description | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------| | `databaseKey` | Set the database key (default is the name of the member). | @@ -134,6 +138,8 @@ extension User: RowConvertible { } ``` +#### Annotations + | Key | Description | | ---------------------- | --------------------------------------------------------------------------------- | | `databaseKey` | Set the database key (default is the name of the member). | @@ -175,6 +181,8 @@ extension User: NodeRepresentable { } ``` +#### Annotations + | Key | Description | | ------------------------- | ------------------------------------------------------------------------------------| | `nodeKey` | Set the key for node (de)serialization. | @@ -222,6 +230,8 @@ extension User: JSONConvertible { extension User: ResponseRepresentable {} ``` +#### Annotations + | Key | Description | | ----------------------- | ----------------------------------------------------------------------------------| | `jsonValue` | Set the value for JSON serialization. | @@ -234,6 +244,8 @@ These templates are related to unit testing with XCTest. ## LinuxMain Generates a static `allTests` for every `XCTestCase` and registers them in the `LinuxMain.swift`. +#### Annotations + | Key | Description | | ----------------------| ----------------------------------------------------------------- | | `excludeFromLinuxMain`| Prevents the test case from being included in the generated code. | @@ -242,6 +254,9 @@ Generates a static `allTests` for every `XCTestCase` and registers them in the ` These templates are for controllers and route collections. ## Route collection + +#### Annotations + | Key | Description | | ------------| ----------- | | `controller`| | From 0861df6e3f61a41b4824b660329cd4cd6797aca2 Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Thu, 5 Oct 2017 13:20:21 +0200 Subject: [PATCH 3/4] Retabbed files --- Models/NodeRepresentable.stencil | 36 +++++++++++++-------------- Models/Preparation.stencil | 42 ++++++++++++++++---------------- Models/RowConvertible.stencil | 30 +++++++++++------------ 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/Models/NodeRepresentable.stencil b/Models/NodeRepresentable.stencil index ca1f8fd..caaf7b5 100644 --- a/Models/NodeRepresentable.stencil +++ b/Models/NodeRepresentable.stencil @@ -14,27 +14,27 @@ import {{ var }} {% endif %} extension {{ type.localName }}: NodeRepresentable { - internal enum NodeKeys: String { - {% for var in type.storedVariables|!annotated:"ignore" %} - case {{ var.annotations.nodeKey|default:var.name }} - {% endfor %} - } + internal enum NodeKeys: String { + {% for var in type.storedVariables|!annotated:"ignore" %} + case {{ var.annotations.nodeKey|default:var.name }} + {% endfor %} + } - // MARK: - NodeRepresentable ({{ type.name }}) - func makeNode(in context: Context?) throws -> Node { - var node = Node([:]) + // MARK: - NodeRepresentable ({{ type.name }}) + func makeNode(in context: Context?) throws -> Node { + var node = Node([:]) - try node.set({{ type.name }}.idKey, id) - {% for var in type.storedVariables|!annotated:"ignore" %} - try node.set(NodeKeys.{{ var.annotations.nodeKey|default:var.name }}.rawValue, {{ var.annotations.nodeValue|default:var.name }}) - {% endfor %} - {% if type.based.Timestampable %} - try node.set({{ type.localName }}.createdAtKey, createdAt) - try node.set({{ type.localName }}.updatedAtKey, updatedAt) - {% endif %} + try node.set({{ type.name }}.idKey, id) + {% for var in type.storedVariables|!annotated:"ignore" %} + try node.set(NodeKeys.{{ var.annotations.nodeKey|default:var.name }}.rawValue, {{ var.annotations.nodeValue|default:var.name }}) + {% endfor %} + {% if type.based.Timestampable %} + try node.set({{ type.localName }}.createdAtKey, createdAt) + try node.set({{ type.localName }}.updatedAtKey, updatedAt) + {% endif %} - return node - } + return node + } } // sourcery:end diff --git a/Models/Preparation.stencil b/Models/Preparation.stencil index 1168de5..bfbf3d9 100644 --- a/Models/Preparation.stencil +++ b/Models/Preparation.stencil @@ -14,30 +14,30 @@ import {{ var }} {% endif %} extension {{ type.localName }}: Preparation { - internal enum DatabaseKeys { - static let id = {{ type.localName }}.idKey - {% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignorePreparation" %} - static let {{ var.annotations.databaseKey|default:var.name }} = "{{ var.annotations.databaseKey|default:var.name }}" - {% endfor %} - } + internal enum DatabaseKeys { + static let id = {{ type.localName }}.idKey + {% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignorePreparation" %} + static let {{ var.annotations.databaseKey|default:var.name }} = "{{ var.annotations.databaseKey|default:var.name }}" + {% endfor %} + } - // MARK: - Preparations ({{ type.name }}) - internal static func prepare(_ database: Database) throws { - try database.create(self) { - $0.id() - {% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignorePreparation" %} - $0.{% if var|annotated:"preparation" %}{{ var.annotations.preparation }}{% elif var|annotated:"enumName" %}enum{% else %}{{ var.typeName.description|lowercase|replace:"?","" }}{% endif %}{% if var.annotations.preparation == "foreignId" %}(for: {{ var.annotations.foreignTable }}.self, optional: {% if var.isOptional %}true{% else %}false{% endif %}, unique: {{ var.annotations.unique }}, foreignIdKey: {% if var.annotations.foreignIdKey %}"{{ var.annotations.foreignIdKey }}"{% else %}DatabaseKeys.{{ var.name }}{% if var.annotations.foreignKeyName %}, foreignKeyName: "{{ var.annotations.foreignKeyName }}"{% endif %}{% endif %}){% elif var.annotations.enumName %}(DatabaseKeys.{% if var.annotations.databaseKey %}{{ var.annotations.databaseKey }}{% else %}{{ var.name }}{% endif %}, options: {{ var.annotations.enumName }}.allDescription){% else %}(DatabaseKeys.{% if var.annotations.databaseKey %}{{ var.annotations.databaseKey }}{% else %}{{ var.name }}{% endif %}{% if var.annotations.type %}, type: "{{ var.annotations.type }}"{% endif %}{% if var.isOptional %}, optional: true{% endif %}{% if var.annotations.unique %}, unique: true{% endif %}){% endif %} - {% endfor %} - } + // MARK: - Preparations ({{ type.name }}) + internal static func prepare(_ database: Database) throws { + try database.create(self) { + $0.id() + {% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignorePreparation" %} + $0.{% if var|annotated:"preparation" %}{{ var.annotations.preparation }}{% elif var|annotated:"enumName" %}enum{% else %}{{ var.typeName.description|lowercase|replace:"?","" }}{% endif %}{% if var.annotations.preparation == "foreignId" %}(for: {{ var.annotations.foreignTable }}.self, optional: {% if var.isOptional %}true{% else %}false{% endif %}, unique: {{ var.annotations.unique }}, foreignIdKey: {% if var.annotations.foreignIdKey %}"{{ var.annotations.foreignIdKey }}"{% else %}DatabaseKeys.{{ var.name }}{% if var.annotations.foreignKeyName %}, foreignKeyName: "{{ var.annotations.foreignKeyName }}"{% endif %}{% endif %}){% elif var.annotations.enumName %}(DatabaseKeys.{% if var.annotations.databaseKey %}{{ var.annotations.databaseKey }}{% else %}{{ var.name }}{% endif %}, options: {{ var.annotations.enumName }}.allDescription){% else %}(DatabaseKeys.{% if var.annotations.databaseKey %}{{ var.annotations.databaseKey }}{% else %}{{ var.name }}{% endif %}{% if var.annotations.type %}, type: "{{ var.annotations.type }}"{% endif %}{% if var.isOptional %}, optional: true{% endif %}{% if var.annotations.unique %}, unique: true{% endif %}){% endif %} + {% endfor %} + } - {% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignorePreparation"|annotated:"index" %} - try database.index(DatabaseKeys.{% if var.annotations.databaseKey %}{{ var.annotations.databaseKey }}{% else %}{{ var.name }}{% endif %}, for: {{ type.name }}.self) - {% endfor %} - } + {% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignorePreparation"|annotated:"index" %} + try database.index(DatabaseKeys.{% if var.annotations.databaseKey %}{{ var.annotations.databaseKey }}{% else %}{{ var.name }}{% endif %}, for: {{ type.name }}.self) + {% endfor %} + } - internal static func revert(_ database: Database) throws { - try database.delete(self) - } + internal static func revert(_ database: Database) throws { + try database.delete(self) + } } // sourcery:end {% endfor %} diff --git a/Models/RowConvertible.stencil b/Models/RowConvertible.stencil index f31e121..6dbf45f 100644 --- a/Models/RowConvertible.stencil +++ b/Models/RowConvertible.stencil @@ -7,24 +7,24 @@ import Vapor import Fluent extension {{ type.localName }}: RowConvertible { - // MARK: - RowConvertible ({{ type.name }}) - convenience internal init (row: Row) throws { - try self.init( - {% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignoreRowConvertible" %} - {{ var.name }}: row.get(DatabaseKeys.{{ var.annotations.databaseKey|default:var.name }}){% if not forloop.last %},{% endif %} - {% endfor %} - ) - } + // MARK: - RowConvertible ({{ type.name }}) + convenience internal init (row: Row) throws { + try self.init( + {% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignoreRowConvertible" %} + {{ var.name }}: row.get(DatabaseKeys.{{ var.annotations.databaseKey|default:var.name }}){% if not forloop.last %},{% endif %} + {% endfor %} + ) + } - internal func makeRow() throws -> Row { - var row = Row() + internal func makeRow() throws -> Row { + var row = Row() - {% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignoreRowConvertible" %} - try row.set(DatabaseKeys.{{ var.annotations.databaseKey|default:var.name }}, {{ var.name }}) - {% endfor %} + {% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignoreRowConvertible" %} + try row.set(DatabaseKeys.{{ var.annotations.databaseKey|default:var.name }}, {{ var.name }}) + {% endfor %} - return row - } + return row + } } // sourcery:end {% endfor %} From 2fd82c5f4d8eace39679f12b7cd12f0710dc1bea Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Thu, 5 Oct 2017 13:21:28 +0200 Subject: [PATCH 4/4] Retabbed README --- README.md | 120 +++++++++++++++++++++++++++--------------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 61f1e40..e511274 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ Automatically generates an initializer and an enum for MySQL enum types. Example: ```swift final class User: Model { - var name: String - var age: Int? + var name: String + var age: Int? } ``` @@ -19,8 +19,8 @@ Becomes: ```swift // sourcery: model final class User: Model { - var name: String - var age: Int? + var name: String + var age: Int? // sourcery:inline:auto:User.Models let storage = Storage() @@ -52,8 +52,8 @@ Generates a list of database keys, automates `prepare` and `revert` functions. Example: ```swift final class User: Model { - var name: String - var age: Int? + var name: String + var age: Int? } ``` @@ -63,25 +63,25 @@ import Vapor import Fluent extension User: Preparation { - internal enum DatabaseKeys { - static let id = User.idKey - static let name = "name" - static let age = "age" - } - - // MARK: - Preparations (User) - internal static func prepare(_ database: Database) throws { - try database.create(self) { - $0.id() - $0.string(DatabaseKeys.name) - $0.int(DatabaseKeys.age, optional: true) - } - - } - - internal static func revert(_ database: Database) throws { - try database.delete(self) - } + internal enum DatabaseKeys { + static let id = User.idKey + static let name = "name" + static let age = "age" + } + + // MARK: - Preparations (User) + internal static func prepare(_ database: Database) throws { + try database.create(self) { + $0.id() + $0.string(DatabaseKeys.name) + $0.int(DatabaseKeys.age, optional: true) + } + + } + + internal static func revert(_ database: Database) throws { + try database.delete(self) + } } ``` @@ -108,8 +108,8 @@ Automates `init (row: Row)` and `makeRow` boilerplate. Example: ```swift final class User: Model { - var name: String - var age: Int? + var name: String + var age: Int? } ``` @@ -119,22 +119,22 @@ import Vapor import Fluent extension User: RowConvertible { - // MARK: - RowConvertible (User) - convenience internal init (row: Row) throws { - try self.init( - name: row.get(DatabaseKeys.name), - age: row.get(DatabaseKeys.age) - ) - } - - internal func makeRow() throws -> Row { - var row = Row() - - try row.set(DatabaseKeys.name, name) - try row.set(DatabaseKeys.age, age) - - return row - } + // MARK: - RowConvertible (User) + convenience internal init (row: Row) throws { + try self.init( + name: row.get(DatabaseKeys.name), + age: row.get(DatabaseKeys.age) + ) + } + + internal func makeRow() throws -> Row { + var row = Row() + + try row.set(DatabaseKeys.name, name) + try row.set(DatabaseKeys.age, age) + + return row + } } ``` @@ -152,8 +152,8 @@ Generates a list of node keys and `makeNode(in context: Context?)`. Example: ```swift final class User: Model { - var name: String - var age: Int? + var name: String + var age: Int? } ``` @@ -163,21 +163,21 @@ import Vapor import Fluent extension User: NodeRepresentable { - internal enum NodeKeys: String { - case name - case age - } + internal enum NodeKeys: String { + case name + case age + } - // MARK: - NodeRepresentable (User) - func makeNode(in context: Context?) throws -> Node { - var node = Node([:]) + // MARK: - NodeRepresentable (User) + func makeNode(in context: Context?) throws -> Node { + var node = Node([:]) - try node.set(User.idKey, id) - try node.set(NodeKeys.name.rawValue, name) - try node.set(NodeKeys.age.rawValue, age) + try node.set(User.idKey, id) + try node.set(NodeKeys.name.rawValue, name) + try node.set(NodeKeys.age.rawValue, age) - return node - } + return node + } } ``` @@ -195,8 +195,8 @@ Generates a list of JSON keys, `init(json: JSON)` and `makeJSON`. Example: ```swift final class User: Model { - var name: String - var age: Int? + var name: String + var age: Int? } ``` @@ -269,4 +269,4 @@ The package owner for this project is [Steffen](https://github.com/steffendsomme ## 📄 License -This package is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT) \ No newline at end of file +This package is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)