Skip to content

Commit 64b2ad6

Browse files
committed
Add SPIManifestBuilder
1 parent e385c40 commit 64b2ad6

File tree

2 files changed

+111
-2
lines changed

2 files changed

+111
-2
lines changed

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@ $(PACKAGE_PATHS): $(SOURCE_DIRS)
5151
swift Scripts/PackageBuilder.swift "$@"
5252
@$(MAKE) commit file="$@"
5353

54+
.spi.yml: $(PACKAGE_PATHS)
55+
swift Scripts/SPIManifestBuilder.swift
56+
@$(MAKE) commit file="$@"
57+
5458
# Install
5559
.PHONY: Submodule
56-
install: Submodule $(PACKAGE_PATHS)
57-
60+
install: Submodule .spi.yml

Scripts/SPIManifestBuilder.swift

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//
2+
// SPIManifestBuilder.swift
3+
// GitHubRestAPISwiftOpenAPI
4+
//
5+
// Created by zwc on 2024/1/10.
6+
//
7+
8+
import Foundation
9+
10+
struct ErrorMessage: LocalizedError {
11+
var message: String
12+
var errorDescription: String? { message }
13+
init(message: String, line: Int = #line) {
14+
self.message = "\(line): \(message)"
15+
}
16+
}
17+
18+
/// The generator supports filtering the OpenAPI document prior to generation,
19+
/// which can be useful when generating client code for a subset of a large API,
20+
/// or splitting an implementation of a server across multiple modules.
21+
struct SourcesBuilder {
22+
23+
struct Source {
24+
let folderName: String
25+
let targetName: String
26+
var sourcePath: String { "Sources/\(folderName)" }
27+
var productString: String {
28+
#"""
29+
.library(name: "\#(targetName)", targets: ["\#(targetName)"]),
30+
"""#
31+
}
32+
var targetString: String {
33+
#"""
34+
.target(
35+
name: "\#(targetName)",
36+
dependencies: [
37+
.product(name: "OpenAPIRuntime", package: "swift-openapi-runtime"),
38+
.product(name: "OpenAPIURLSession", package: "swift-openapi-urlsession"),
39+
],
40+
path: "\#(sourcePath)"
41+
),
42+
"""#
43+
}
44+
}
45+
46+
private(set) var sources: [SourcesBuilder.Source] = []
47+
48+
init() throws {
49+
let directoryURL = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
50+
.appending(path: "Sources")
51+
let resourceKeys = Set<URLResourceKey>([.nameKey, .isDirectoryKey])
52+
53+
guard let directoryEnumerator = FileManager.default.enumerator(
54+
at: directoryURL,
55+
includingPropertiesForKeys: Array(resourceKeys),
56+
options: .skipsHiddenFiles) else {
57+
throw ErrorMessage(message: "Variable directoryEnumerator not found.")
58+
}
59+
60+
let sourceURLs = directoryEnumerator.compactMap { $0 as? URL }.filter { fileURL in
61+
guard let resourceValues = try? fileURL.resourceValues(forKeys: resourceKeys),
62+
let isDirectory = resourceValues.isDirectory,
63+
isDirectory,
64+
fileURL.pathComponents.count == directoryURL.pathComponents.count + 1 // Check if it's a direct child
65+
else { return false }
66+
return true
67+
}
68+
69+
sources = sourceURLs.map {
70+
let folderName = $0.lastPathComponent
71+
let targetName = folderName.replacingOccurrences(of: "-", with: "_").capitalized
72+
return Source(folderName: folderName, targetName: "GitHubRestAPI\(targetName)")
73+
}
74+
}
75+
}
76+
77+
struct SPIManifestBuilder {
78+
79+
func getTemplate() throws -> String {
80+
let sources = try SourcesBuilder().sources
81+
let targetNamesString: String = sources.map(\.targetName)
82+
.map { " - \($0)"}
83+
.joined(separator: "\n")
84+
return #"""
85+
version: 1
86+
builder:
87+
configs:
88+
- documentation_targets:
89+
\#(targetNamesString)
90+
"""#
91+
}
92+
93+
func write() throws {
94+
let fileURL = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
95+
.appending(path: ".spi.yml")
96+
let fileContent = try getTemplate()
97+
guard let data = fileContent.data(using: .utf8) else {
98+
throw ErrorMessage(message: "Variable data not found.")
99+
}
100+
try data.write(to: fileURL)
101+
}
102+
103+
}
104+
105+
try SPIManifestBuilder().write()
106+

0 commit comments

Comments
 (0)