@@ -10,17 +10,10 @@ import ArgumentParser
1010import Compiler
1111import SwiftSyntax
1212
13- enum CLIError : Error {
14- case fileIsNotValidUTF8( path: String )
15- case migrationFileNameMustBeNumber( String )
16- case invalidOutput( String )
17- case outputMustBeFileNotDirectory( String )
18- }
19-
2013@main
21- struct Feather : ParsableCommand {
14+ struct Feather : AsyncParsableCommand {
2215 @Option ( name: . shortAndLong, help: " The root directory of the Feather sources " )
23- var path : String ? = nil
16+ var path : String = FileManager . default . currentDirectoryPath
2417
2518 @Option ( name: . shortAndLong, help: " The output file path. Default is to stdout " )
2619 var output : String ? = nil
@@ -31,113 +24,26 @@ struct Feather: ParsableCommand {
3124 @Option ( name: . shortAndLong, help: " Comma separated list of additional imports to add " )
3225 var additionalImports : String ?
3326
34- @Flag ( name: . long, help: " Whether or not the generated models should be namespace under the DB struct " )
35- var namespaceModels : Bool = false
36-
37-
38- mutating func run( ) throws {
39- try generate ( language: SwiftLanguage . self)
40- }
41-
42- @discardableResult
43- private func forEachFile< T> (
44- in path: String ,
45- execute: ( String , String ) throws -> T
46- ) throws -> [ T ] {
47- var result : [ T ] = [ ]
48-
49- for file in try FileManager . default. contentsOfDirectory ( atPath: path) . sorted ( ) {
50- let data = try Data ( contentsOf: URL ( fileURLWithPath: " \( path) / \( file) " ) )
51-
52- guard let source = String ( data: data, encoding: . utf8) else {
53- throw CLIError . fileIsNotValidUTF8 ( path: path)
54- }
55-
56- try result. append ( execute ( source, file) )
57- }
58-
59- return result
27+ mutating func run( ) async throws {
28+ try await generate ( language: SwiftLanguage . self)
6029 }
6130
62- private func generate< Lang: Language > ( language: Lang . Type ) throws {
63- let path = path ?? FileManager . default. currentDirectoryPath
64- var compiler = Compiler ( )
65-
66- try forEachFile ( in: " \( path) /Migrations " ) { file, fileName in
67- let diags = compiler. compile ( migration: file, namespace: . file( fileName) )
68-
69- let numberStr = fileName. split ( separator: " . " ) [ 0 ]
70- guard Int ( numberStr) != nil else {
71- throw CLIError . migrationFileNameMustBeNumber ( fileName)
72- }
73-
74- report ( diagnostics: diags, source: file, forFile: fileName)
75- }
31+ private func generate< Lang: Language > ( language: Lang . Type ) async throws {
32+ let driver = Driver ( )
33+ await driver. add ( reporter: StdoutDiagnosticReporter ( ) )
7634
77- try forEachFile ( in: " \( path) /Queries " ) { file, fileName in
78- let diags = compiler. compile ( queries: file, namespace: . file( fileName) )
79- report ( diagnostics: diags, source: file, forFile: fileName)
80- }
35+ try await driver. compile ( path: path)
8136
82-
83- let file = try Lang . generate (
37+ try await driver. generate (
38+ language: Lang . self,
39+ to: output,
8440 imports: additionalImports? . split ( separator: " , " ) . map ( \. description) ?? [ ] ,
8541 databaseName: databaseName,
86- migrations: compiler. migrations. map ( \. sanitizedSource) ,
87- queries: compiler. queries. map { ( $0. key. file? . split ( separator: " . " ) . first? . description, $0. value) } ,
88- schema: compiler. schema,
8942 options: gatherOptions ( )
9043 )
91-
92- guard !compiler. hasDiagnostics else {
93- return
94- }
95-
96- if let output {
97- try validateIsFile ( output)
98- try createDirectoiesIfNeeded ( output)
99-
100- try file. write ( toFile: output, atomically: true , encoding: . utf8)
101- } else {
102- // No output directory, just print to stdout
103- print ( file)
104- }
10544 }
10645
10746 private func gatherOptions( ) -> GenerationOptions {
108- var options : GenerationOptions = [ ]
109-
110-
111- return options
112- }
113-
114- private func createDirectoiesIfNeeded( _ output: String ) throws {
115- let url = URL ( fileURLWithPath: output)
116- let directory = url. deletingLastPathComponent ( )
117-
118- guard !FileManager. default. fileExists ( atPath: directory. path) else { return }
119-
120- try FileManager . default. createDirectory (
121- atPath: directory. path,
122- withIntermediateDirectories: true
123- )
124- }
125-
126- private func validateIsFile( _ output: String ) throws {
127- if output. split ( separator: " . " ) . count <= 1 {
128- throw CLIError . outputMustBeFileNotDirectory ( output)
129- }
130- }
131-
132- private func report(
133- diagnostics: Diagnostics ,
134- source: String ,
135- forFile fileName: String
136- ) {
137- let reporter = StdoutDiagnosticReporter ( )
138-
139- for diag in diagnostics. elements {
140- reporter. report ( diagnostic: diag, source: source, fileName: fileName)
141- }
47+ return [ ] // This originally had options
14248 }
14349}
0 commit comments