Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,38 @@ jobs:
- name: Test
run: swift test -v

examples:
name: Build examples
runs-on: macos-latest
steps:
- uses: actions/checkout@v7.0.1
# The example file is not part of any target, so it would otherwise rot
# unnoticed. Build it the way a consumer would: as its own package
# depending on this one by path.
- name: Build Examples against the package
run: |
mkdir -p /tmp/example-consumer/Sources/ExampleConsumer
cp Examples/*.swift /tmp/example-consumer/Sources/ExampleConsumer/
cat > /tmp/example-consumer/Package.swift <<'MANIFEST'
// swift-tools-version: 6.0
import PackageDescription

let package = Package(
name: "ExampleConsumer",
platforms: [.macOS(.v13)],
dependencies: [.package(path: "PACKAGE_PATH")],
targets: [
.target(
name: "ExampleConsumer",
dependencies: [.product(name: "SwiftAppleScriptBridge", package: "SwiftAppleScriptBridge")],
swiftSettings: [.swiftLanguageMode(.v5)]
)
]
)
MANIFEST
sed -i '' "s|PACKAGE_PATH|$GITHUB_WORKSPACE|" /tmp/example-consumer/Package.swift
cd /tmp/example-consumer && swift build

lint:
name: SwiftLint
runs-on: macos-latest
Expand Down
7 changes: 6 additions & 1 deletion .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ disabled_rules:
- identifier_name
# Test files are one type per concern, not one per file.
- type_name
# The character-scanning loops chain `else if` on their own lines, one branch
# per line, which reads better than trailing them onto the closing brace.
- statement_position

opt_in_rules:
- empty_count
Expand All @@ -26,7 +29,9 @@ force_unwrapping:
severity: warning

cyclomatic_complexity:
warning: 15
# parseSimpleAppleScriptRecord is a character scanner, and splitting its
# branches across functions would make it harder to follow, not easier.
warning: 20
error: 25

function_body_length:
Expand Down
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

Nothing yet.

## [1.0.1] — 2026-08-16

No functional change: the public API, and what every method does, are identical to 1.0.0.

### Added

- `Examples/AppleScripts.swift`, showing the one-file-of-scripts layout with a script for every return type, the three placeholder forms, a raw AppleScript list, and the Swift call site for each. CI builds it as a consumer package so it cannot rot.
- README section on Swift 6 language mode. `AppleScriptObject` is not `Sendable`, so declaring scripts as `static let` needs `nonisolated(unsafe)` there. Removing that requirement is tracked in [#2](https://github.com/fredsimard/SwiftAppleScriptBridge/issues/2).
- `Documentation/API.md`, a reference for every public symbol.
- `CONTRIBUTING.md`, `SECURITY.md`, and issue and pull request templates.

### Changed

- Dropped four redundant `?? nil` coalescings in `executeAppleScript(_:with:)`, where the expression was already optional and the return type is `Any?`. Same results, same types.
- SwiftLint now fails the build on any violation, with the rules that conflict with the codebase's deliberate style disabled and annotated.

## [1.0.0] — 2026-08-16

First public release.
Expand All @@ -30,5 +46,6 @@ First public release.
- Ships in Swift 5 language mode. `AppleScriptObject` carries `[String: Any]`, which is not `Sendable`; a strict-concurrency redesign is planned for 2.0.
- An app using this package cannot be sandboxed and so cannot ship on the Mac App Store. Developer ID signing and notarization are unaffected.

[Unreleased]: https://github.com/fredsimard/SwiftAppleScriptBridge/compare/v1.0.0...HEAD
[Unreleased]: https://github.com/fredsimard/SwiftAppleScriptBridge/compare/v1.0.1...HEAD
[1.0.1]: https://github.com/fredsimard/SwiftAppleScriptBridge/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/fredsimard/SwiftAppleScriptBridge/releases/tag/v1.0.0
8 changes: 4 additions & 4 deletions Sources/SwiftAppleScriptBridge/AppleScriptBridge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,11 @@ public class AppleScriptBridge: NSObject {

switch AppleScript.returnType {
case .int: return Int(result.int32Value)
case .string: return result.stringValue ?? nil
case .string: return result.stringValue
case .bool: return result.int32Value != 0 ? true : false
case .list: return result.stringValue?.components(separatedBy: .newlines) ?? nil
case .record: return result.stringValue?.parseSimpleAppleScriptRecord() ?? nil
case .json: return result.stringValue?.parseJSONStringFromAppleScript() ?? nil
case .list: return result.stringValue?.components(separatedBy: .newlines)
case .record: return result.stringValue?.parseSimpleAppleScriptRecord()
case .json: return result.stringValue?.parseJSONStringFromAppleScript()
case .none: return nil
}
}
Expand Down
3 changes: 3 additions & 0 deletions Sources/SwiftAppleScriptBridge/StringExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ extension String {
///
/// - Returns: A POSIX-style file system path as a `String`, or `nil` if the conversion fails.
public func toPOSIXPath() -> String? {
// `1` is CFURLPathStyle.cfurlHFSPathStyle, which is deprecated in the Swift overlay but
// is still what this call needs; the raw value is fixed, so the initializer cannot fail.
// swiftlint:disable:next force_unwrapping
guard let fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, self as CFString?, CFURLPathStyle(rawValue: 1)!, self.hasSuffix(":")) else { return nil }
return (fileURL as URL).path
}
Expand Down
Loading