Files
xtool-mirror/Sources/PackLib/PackSchema.swift
Erik Bautista Santibanez edd6b90f53 Add support for App Extensions (#97)
This pull request adds support for Apple's [App
Extensions](https://developer.apple.com/app-extensions/).

Closes: #45

---------

Co-authored-by: ErrorErrorError <16653389+ErrorErrorError@users.noreply.github.com>
Co-authored-by: Kabir Oberai <oberai.kabir@gmail.com>
2025-07-13 23:47:47 -04:00

92 lines
2.5 KiB
Swift

import Foundation
import Yams
public struct PackSchemaBase: Codable, Sendable {
public enum Version: Int, Codable, Sendable {
case v1 = 1
}
public var version: Version
public var orgID: String?
public var bundleID: String?
public var product: String?
public var infoPath: String?
public var entitlementsPath: String?
public var iconPath: String?
public var resources: [String]?
public var extensions: [Extension]?
public struct Extension: Codable, Sendable {
public var product: String
public var bundleID: String?
public var infoPath: String
public var resources: [String]?
public var entitlementsPath: String?
}
}
@dynamicMemberLookup
public struct PackSchema: Sendable {
public typealias Extension = PackSchemaBase.Extension
public enum IDSpecifier: Sendable {
case orgID(String)
case bundleID(String)
func formBundleID(product: String) -> String {
switch self {
case .orgID(let orgID): "\(orgID).\(product)"
case .bundleID(let bundleID): bundleID
}
}
}
public let base: PackSchemaBase
public let idSpecifier: IDSpecifier
public init(validating base: PackSchemaBase) throws {
self.base = base
if base.version != .v1 {
throw StringError("xtool.yml: Unsupported schema version: \(base.version.rawValue)")
}
switch (base.bundleID, base.orgID) {
case (let bundleID?, _):
idSpecifier = .bundleID(bundleID)
case (nil, let orgID?):
idSpecifier = .orgID(orgID)
case (nil, nil):
throw StringError("xtool.yml: Must specify either orgID or bundleID")
}
if let iconPath = base.iconPath {
let ext = URL(fileURLWithPath: iconPath).pathExtension
guard ext == "png" else {
throw StringError("xtool.yml: iconPath should have a 'png' path extension. Got '\(ext)'.")
}
}
}
// swiftlint:disable:next force_try
public static let `default` = try! PackSchema(validating: .init(
version: .v1,
orgID: "com.example"
))
public init(url: URL) async throws {
let data = try await Data(reading: url)
let base = try YAMLDecoder().decode(PackSchemaBase.self, from: data)
try self.init(validating: base)
}
public subscript<Subject>(dynamicMember keyPath: KeyPath<PackSchemaBase, Subject>) -> Subject {
self.base[keyPath: keyPath]
}
}