Skip to content
This repository was archived by the owner on Apr 20, 2024. It is now read-only.

Commit 629ecbc

Browse files
Merge pull request #16 from nodes-vapor/enum-all-cases
Allcases support for enums
2 parents ce39951 + 1b49515 commit 629ecbc

7 files changed

Lines changed: 198 additions & 114 deletions

File tree

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,20 @@
11
{# One route file per model #}
22

33
{% for type in types.all|!protocol|annotated:"controller" %}
4-
// sourcery:file:Routes/{{ type.localName|replace:"Controller","" }}Routes/{{ type.localName|replace:"Controller","" }}Routes.generated.swift
4+
// sourcery:file:Routes/{{ type.localName }}/{{ type.localName }}+RouteCollection.generated.swift
55

66
import Vapor
77

8-
final class {{ type.localName|replace:"Controller","" }}Routes: RouteCollection {
9-
private let controller: {{ type.localName }}
10-
private let middlewares: [Middleware]
11-
12-
internal init(
13-
controller: {{ type.localName }},
14-
middlewares: [Middleware] = []
15-
) {
16-
self.controller = controller
17-
self.middlewares = middlewares
18-
}
19-
8+
extension {{ type.localName }}: RouteCollection {
209
func build(_ builder: RouteBuilder) throws {
21-
builder.grouped("{{ type.annotations.group }}").group(middleware: middlewares) { routes in
10+
builder.group("{{ type.annotations.group }}") { routes in
2211
{% for func in type.methods where func|annotated:"route" %}
2312
// {{ func.annotations.method|uppercase }} /{{ type.annotations.group }}{{ func.annotations.path }}
24-
routes.{{ func.annotations.method }}("{{ func.annotations.path }}", handler: controller.{{ func.shortName }})
13+
routes.{{ func.annotations.method }}("{{ func.annotations.path }}", handler: {{ func.shortName }})
2514
{% endfor %}
2615
}
2716
}
2817
}
18+
2919
// sourcery:end
3020
{% endfor %}

General/Enum.stencil

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import Node
2+
import Vapor
3+
4+
/// Enables an enumeration to be convertable to-and-from a Node implicitly,
5+
/// without having to use `Enum.case.rawValue`.
6+
///
7+
/// Example:
8+
/// ```
9+
/// enum State: String, RawStringConvertible {
10+
/// case pending
11+
/// case accepted
12+
/// }
13+
///
14+
/// let state: State = .pending
15+
///
16+
/// node["state"] = state
17+
///
18+
/// let stateFromNode: State = try node.extract("state")
19+
///
20+
/// ```
21+
public protocol RawStringConvertible: NodeConvertible {
22+
init?(rawValue: String)
23+
var rawValue: String { get }
24+
}
25+
26+
extension RawStringConvertible {
27+
public init(node: Node) throws {
28+
guard let string = node.string else {
29+
throw Abort(
30+
.internalServerError,
31+
metadata: nil,
32+
reason: "Expected a String"
33+
)
34+
}
35+
36+
guard let state = Self.init(rawValue: string) else {
37+
throw Abort(
38+
.internalServerError,
39+
metadata: nil,
40+
reason: "Invalid case: \(string)"
41+
)
42+
}
43+
44+
self = state
45+
}
46+
47+
public func makeNode(in context: Context?) throws -> Node {
48+
return .string(self.rawValue)
49+
}
50+
}
51+
52+
// MARK: Enums
53+
54+
{% for enum in types.enums|!annotated:"ignore" where arguments.enumOptOut or enum.annotations.enum or enum.based.RawStringConvertible %}
55+
56+
extension {{ enum.name }} {
57+
static var all: [{{ enum.name }}] = [
58+
{% for case in enum.cases %}
59+
.{{ case.name }},
60+
{% endfor %}
61+
]
62+
63+
static let allRaw = {{ enum.name }}.all.map { $0.rawValue }
64+
}
65+
66+
{% endfor %}

Models/JSONConvertible.stencil

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ import {{ var }}
1616
extension {{ type.localName }}: JSONConvertible {
1717
internal enum JSONKeys: String {
1818
{% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignoreJSONConvertible" %}
19-
case {% if var.annotations.jsonKey %}{{ var.annotations.jsonKey }}{% else %}{{ var.name }}{% endif %}
19+
static let {{ var.annotations.jsonKey|default:var.name }} = "{{ var.annotations.jsonKey|default:var.name }}"
2020
{% endfor %}
2121
}
2222

2323
// MARK: - JSONConvertible ({{ type.name }})
2424
internal convenience init(json: JSON) throws {
2525
try self.init(
2626
{% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignoreJSONConvertible" %}
27-
{{ var.name }}: json.get(JSONKeys.{{ var.annotations.jsonKey|default:var.name }}.rawValue){% if not forloop.last %},{% endif %}
27+
{{ var.name }}: json.get(JSONKeys.{{ var.annotations.jsonKey|default:var.name }}){% if not forloop.last %},{% endif %}
2828
{% endfor %}
2929
)
3030
}
@@ -34,7 +34,7 @@ extension {{ type.localName }}: JSONConvertible {
3434

3535
try json.set({{ type.name }}.idKey, id)
3636
{% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignoreJSONConvertible" %}
37-
try json.set(JSONKeys.{{ var.annotations.jsonKey|default:var.name }}.rawValue, {{ var.annotations.jsonValue|default:var.name}})
37+
try json.set(JSONKeys.{{ var.annotations.jsonKey|default:var.name }}, {{ var.annotations.jsonValue|default:var.name}})
3838
{% endfor %}
3939

4040
return json

Models/Model.stencil

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,7 @@
22

33
{% for type in types.based.Model|!protocol|annotated:"model" %}
44
// sourcery:inline:auto:{{ type.name }}.Models
5-
let storage = Storage()
6-
7-
{% for var in type.storedVariables|!annotated:"ignore"|annotated:"enumName" %}
8-
enum {{ var.annotations.enumName }}: {{ var.annotations.enumType }}, RawStringConvertible {
9-
{% for case in var.annotations.enumCase %}
10-
case {{ case }}
11-
{% endfor %}
12-
13-
static let all = [{% for case in var.annotations.enumCase %}{{ var.annotations.enumName }}.{{ case }}{% if not forloop.last %}, {% endif %}{% endfor %}]
14-
static let allDescription = {{ var.annotations.enumName }}.all.map { $0.rawValue }
15-
}
16-
{% endfor %}
5+
internal let storage = Storage()
176

187
internal init(
198
{% for var in type.storedVariables|!annotated:"ignore" %}

Models/NodeRepresentable.stencil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import {{ var }}
1515

1616
extension {{ type.localName }}: NodeRepresentable {
1717
internal enum NodeKeys: String {
18-
{% for var in type.storedVariables|!annotated:"ignore" %}
19-
case {{ var.annotations.nodeKey|default:var.name }}
18+
{% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignoreNodeRepresentable" %}
19+
static let {{ var.annotations.nodeKey|default:var.name }} = "{{ var.annotations.nodeKey|default:var.name }}"
2020
{% endfor %}
2121
}
2222

@@ -25,8 +25,8 @@ extension {{ type.localName }}: NodeRepresentable {
2525
var node = Node([:])
2626

2727
try node.set({{ type.name }}.idKey, id)
28-
{% for var in type.storedVariables|!annotated:"ignore" %}
29-
try node.set(NodeKeys.{{ var.annotations.nodeKey|default:var.name }}.rawValue, {{ var.annotations.nodeValue|default:var.name }})
28+
{% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignoreNodeRepresentable" %}
29+
try node.set(NodeKeys.{{ var.annotations.nodeKey|default:var.name }}, {{ var.annotations.nodeValue|default:var.name }})
3030
{% endfor %}
3131
{% if type.based.Timestampable %}
3232
try node.set({{ type.localName }}.createdAtKey, createdAt)

Models/Preparation.stencil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ extension {{ type.localName }}: Preparation {
2626
try database.create(self) {
2727
$0.id()
2828
{% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignorePreparation" %}
29-
$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 %}
29+
$0.{% if var|annotated:"preparation" %}{{ var.annotations.preparation }}{% elif var.type.based.RawStringConvertible %}enum{% else %}{{ var.typeName.description|lowercase|replace:"?","" }}{% endif %}{% if var.annotations.preparation == "foreignId" %}(for: {{ var.annotations.foreignTable }}.self, optional: {{ var.isOptional }}, 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.type.based.RawStringConvertible %}(DatabaseKeys.{% if var.annotations.databaseKey %}{{ var.annotations.databaseKey }}{% else %}{{ var.name }}{% endif %}, options: {{ var.typeName }}.allRaw){% 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 %}
3030
{% endfor %}
3131
}
3232

3333
{% for var in type.storedVariables|!annotated:"ignore"|!annotated:"ignorePreparation"|annotated:"index" %}
34-
try database.index(DatabaseKeys.{% if var.annotations.databaseKey %}{{ var.annotations.databaseKey }}{% else %}{{ var.name }}{% endif %}, for: {{ type.name }}.self)
34+
try database.index(DatabaseKeys.{{ var.annotations.databaseKey|default:var.name }}, for: {{ type.name }}.self)
3535
{% endfor %}
3636
}
3737

0 commit comments

Comments
 (0)