Skip to content

Commit 7af3794

Browse files
Add filter CLI command
1 parent 46736fc commit 7af3794

File tree

3 files changed

+102
-1
lines changed

3 files changed

+102
-1
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftOpenAPIGenerator open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the SwiftOpenAPIGenerator project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftOpenAPIGenerator project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
import ArgumentParser
15+
import Foundation
16+
import _OpenAPIGeneratorCore
17+
import Yams
18+
import OpenAPIKit
19+
import OpenAPIKit30
20+
21+
struct _FilterCommand: AsyncParsableCommand {
22+
static var configuration = CommandConfiguration(
23+
commandName: "filter",
24+
abstract: "Filter an OpenAPI document",
25+
discussion: """
26+
Filtering rules are provided in a YAML configuration file.
27+
28+
Example configuration file contents:
29+
30+
```yaml
31+
\(try! YAMLEncoder().encode(sampleConfig))
32+
```
33+
"""
34+
)
35+
36+
@Option(help: "Path to a YAML configuration file.")
37+
var config: URL
38+
39+
@Argument(help: "Path to the OpenAPI document, either in YAML or JSON.")
40+
var docPath: URL
41+
42+
func parseOpenAPIDocument(_ documentData: Data) throws -> OpenAPIKit.OpenAPI.Document {
43+
let decoder = YAMLDecoder()
44+
45+
struct OpenAPIVersionedDocument: Decodable {
46+
var openapi: String
47+
}
48+
49+
let versionedDocument = try decoder.decode(OpenAPIVersionedDocument.self, from: documentData)
50+
51+
let document: OpenAPIKit.OpenAPI.Document
52+
switch versionedDocument.openapi {
53+
case "3.0.0", "3.0.1", "3.0.2", "3.0.3":
54+
let document30x = try decoder.decode(OpenAPIKit30.OpenAPI.Document.self, from: documentData)
55+
document = document30x.convert(to: .v3_1_0)
56+
case "3.1.0":
57+
document = try decoder.decode(OpenAPIKit.OpenAPI.Document.self, from: documentData)
58+
default:
59+
fatalError("Unsupported OpenAPI version found: \(versionedDocument.openapi)")
60+
}
61+
return document
62+
}
63+
64+
func run() async throws {
65+
let configData = try Data(contentsOf: config)
66+
let config = try YAMLDecoder().decode(_UserConfig.self, from: configData)
67+
let document = try timing("Parsing document", parseOpenAPIDocument(Data(contentsOf: docPath)))
68+
try document.validate()
69+
guard let documentFilter = config.filter else {
70+
FileHandle.standardError.write("warning: No filter config provided\n")
71+
FileHandle.standardOutput.write(try YAMLEncoder().encode(document))
72+
return
73+
}
74+
let filteredDocument = try timing("Filtering document", documentFilter.filter(document))
75+
FileHandle.standardOutput.write(try YAMLEncoder().encode(filteredDocument))
76+
}
77+
}
78+
79+
private func timing<Output>(_ title: String, operation: () throws -> Output) rethrows -> Output {
80+
FileHandle.standardError.write("\(title)...\n")
81+
let start = Date.timeIntervalSinceReferenceDate
82+
let result = try operation()
83+
let diff = Date.timeIntervalSinceReferenceDate - start
84+
FileHandle.standardError.write(String(format: "\(title) complete! (%.2fs)\n", diff))
85+
return result
86+
}
87+
88+
private func timing<Output>(_ title: String, _ operation: @autoclosure () throws -> Output) rethrows -> Output {
89+
try timing(title, operation: operation)
90+
}
91+
92+
private let sampleConfig = _UserConfig(
93+
generate: [],
94+
filter: DocumentFilter(
95+
tags: ["greetings"],
96+
paths: ["/greeting"],
97+
schemas: ["Greeting"]
98+
)
99+
)

Sources/swift-openapi-generator/Tool.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ struct _Tool: AsyncParsableCommand {
1919
commandName: "swift-openapi-generator",
2020
abstract: "Generate Swift client and server code from an OpenAPI document",
2121
subcommands: [
22-
_GenerateCommand.self
22+
_FilterCommand.self,
23+
_GenerateCommand.self,
2324
]
2425
)
2526
}

Sources/swift-openapi-generator/UserConfig.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct _UserConfig: Codable {
3939
enum CodingKeys: String, CaseIterable, CodingKey {
4040
case generate
4141
case additionalImports
42+
case filter
4243
case featureFlags
4344
}
4445
}

0 commit comments

Comments
 (0)