@@ -31,6 +31,11 @@ public actor Driver {
3131 case alwaysMigration
3232 }
3333
34+ enum Error : Swift . Error {
35+ case invalidMigrationName( String )
36+ case canOnlyHaveOneAlwaysMigration
37+ }
38+
3439 init ( fileSystem: FileSystem ) {
3540 self . fileSystem = fileSystem
3641 }
@@ -47,14 +52,21 @@ public actor Driver {
4752 let migrationsPath = migrationsPath ( at: path)
4853 let queriesPath = queriesPath ( at: path)
4954
50- let migrationFiles = try fileSystem. files ( atPath: migrationsPath)
55+ let ( migrationFiles, alwaysMigration) = try organizeMigrations (
56+ fileNames: fileSystem. files ( atPath: migrationsPath)
57+ )
5158 let queriesFiles = try fileSystem. files ( atPath: queriesPath)
5259
5360 // Migrations must be run synchronously in order.
5461 for migration in migrationFiles {
5562 try compile ( file: migration, in: migrationsPath, usage: . migration)
5663 }
5764
65+ // Always migrations always run after
66+ if let alwaysMigration {
67+ try compile ( file: alwaysMigration, in: migrationsPath, usage: . migration)
68+ }
69+
5870 // Queries can be compiled independently
5971 try await withThrowingTaskGroup ( of: Void . self) { group in
6072 for query in queriesFiles {
@@ -82,8 +94,15 @@ public actor Driver {
8294 . filter { $0. usage == . queries }
8395 . map { ( $0. fileName. split ( separator: " . " ) . first? . description, $0. statements) }
8496
97+ let alwaysMigration = results. values
98+ . first { $0. usage == . alwaysMigration } ?
99+ . statements
100+ . map ( \. sanitizedSource)
101+ . joined ( )
102+
85103 let file = try Lang . generate (
86104 migrations: migrations,
105+ alwaysMigration: alwaysMigration,
87106 queries: queries,
88107 schema: currentSchema,
89108 options: options
@@ -152,4 +171,36 @@ public actor Driver {
152171 private func queriesPath( at base: Path ) -> Path {
153172 " \( base) /Queries "
154173 }
174+
175+ private func organizeMigrations(
176+ fileNames: [ String ]
177+ ) throws -> ( standard: [ String ] , always: String ? ) {
178+ var standard : [ String ] = [ ]
179+ var always : String ?
180+
181+ for fileName in fileNames. sorted ( ) {
182+ var components = fileName. split ( separator: " . " )
183+
184+ guard components. count == 2 else {
185+ throw Error . invalidMigrationName ( fileName)
186+ }
187+
188+ let nameWithoutExt = components [ 0 ]
189+
190+ if Int ( nameWithoutExt) != nil {
191+ standard. append ( fileName)
192+ } else if nameWithoutExt == " Always " {
193+ guard always == nil else {
194+ // Can this really even happen?
195+ throw Error . canOnlyHaveOneAlwaysMigration
196+ }
197+
198+ always = fileName
199+ } else {
200+ throw Error . invalidMigrationName ( fileName)
201+ }
202+ }
203+
204+ return ( standard, always)
205+ }
155206}
0 commit comments