Scaffold v1.0.0

This commit is contained in:
T. R. Bernstein
2026-04-17 01:08:29 +02:00
commit b49d642dfd
22 changed files with 983 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
import Foundation
import PackagePlugin
@main
struct EmbedderPlugin: BuildToolPlugin {
func createBuildCommands(
context: PluginContext,
target: Target
) async throws -> [Command] {
guard let sourceModule = target as? SourceModuleTarget else {
return []
}
return try buildCommands(for: sourceModule, in: context)
}
}
private extension EmbedderPlugin {
static let staticInlineDirectoryName = "Static Inline"
static let generatedFileName = "Embedded.swift"
static let toolName = "EmbedderTool"
func buildCommands(
for target: SourceModuleTarget,
in context: PluginContext
) throws -> [Command] {
guard let staticInlineDirectory = locateStaticInlineDirectory(in: target) else {
return []
}
let inputFiles = try collectInputFiles(under: staticInlineDirectory)
guard !inputFiles.isEmpty else {
return []
}
return [
try makeBuildCommand(
sourceDirectory: staticInlineDirectory,
inputFiles: inputFiles,
context: context
)
]
}
func locateStaticInlineDirectory(in target: SourceModuleTarget) -> URL? {
let candidate = target.directoryURL.appending(path: Self.staticInlineDirectoryName)
return FileSystem.isDirectory(at: candidate) ? candidate : nil
}
func collectInputFiles(under directory: URL) throws -> [URL] {
try FileSystem.regularFiles(under: directory)
}
func makeBuildCommand(
sourceDirectory: URL,
inputFiles: [URL],
context: PluginContext
) throws -> Command {
let tool = try context.tool(named: Self.toolName)
let outputFile = context.pluginWorkDirectoryURL.appending(path: Self.generatedFileName)
return .buildCommand(
displayName: "Embedding files from \(Self.staticInlineDirectoryName)",
executable: tool.url,
arguments: [
sourceDirectory.path(percentEncoded: false),
outputFile.path(percentEncoded: false)
],
inputFiles: inputFiles,
outputFiles: [outputFile]
)
}
}

View File

@@ -0,0 +1,25 @@
import Foundation
enum FileSystem {
static func isDirectory(at url: URL) -> Bool {
let resourceValues = try? url.resourceValues(forKeys: [.isDirectoryKey])
return resourceValues?.isDirectory == true
}
static func regularFiles(under directory: URL) throws -> [URL] {
guard let enumerator = FileManager.default.enumerator(
at: directory,
includingPropertiesForKeys: [.isRegularFileKey],
options: [.skipsHiddenFiles]
) else {
return []
}
return enumerator
.compactMap { $0 as? URL }
.filter(isRegularFile)
}
private static func isRegularFile(_ url: URL) -> Bool {
(try? url.resourceValues(forKeys: [.isRegularFileKey]).isRegularFile) == true
}
}