Repository navigation
The first release since 3.0.1 (2018). It brings the package up to Swift 6 with an async/await API, replaces Perfect-CURL with Foundation's URLSession, and closes a query-injection hole in the percent-encoder. It is a major version: every public method changed shape. Read "Breaking and behaviour changes" before upgrading.
Requirements
- Swift tools 6.2 (
// swift-tools-version: 6.2); 3.0.1 declared 4.0. - Platforms: macOS 12+ and iOS 15+ (newly declared; 3.0.1 declared none), and Linux. On Linux, install
libxml2-devandpkg-configfor Perfect-XML. - Depends on Perfect-XML
from: "4.0.0". Perfect-CURL is no longer a dependency, and neither is PerfectLib, which 3.0.1 got through Perfect-CURL.
.package(url: "https://github.com/PerfectlySoft/Perfect-FileMaker.git", from: "4.0.0")CI now runs on GitHub Actions for every push and pull request: Linux (Swift 6.2 and 6.4) and macOS (Xcode 26.0.1 and 26.6), each in debug and release with warnings treated as errors, plus the tests on an iOS Simulator. There is no FileMaker Server in CI, so it runs the query-building tests and the request/response tests against a mocked URLSession; the seven live-server tests are skipped unless FILEMAKER_TESTS=1 is set. The live tests were not run for this release.
Highlights
async/await(#4).databaseNames(),layoutNames(database:),layoutInfo(database:layout:)andquery(_:)areasync throwsand return their results directly.URLSessionnetworking (#4). Requests go through Foundation instead of Perfect-CURL.FileMakerServer.initgains optional parameters:useTLS:(default: HTTPS only on port 443, as before),urlSession:(default.shared; inject one for testing) anddefaultTimeout:(default 5 seconds of inactivity).Sendable(#4).FileMakerServerand the query and result types areSendable.- Linux and iOS. The package builds and its tests pass on Linux with Swift 6.2 and 6.4, and on the iOS Simulator with Xcode 26.3 and 27; iOS 15 is declared (Perfect-XML 4.0 requires it).
- Swift Testing. The tests moved from XCTest to Swift Testing, with new mocked-network tests for the request layer and regression tests for the escaping fixes (27 tests: 20 run without a server, 7 live). The offline tests cover
layoutInfofield typing and portal definitions, portal records,layoutNamesand error 401.
Breaking and behaviour changes
- Toolchain and platforms. Swift tools 6.2 is required, with macOS 12 or iOS 15 at minimum. Upgrade: use a Swift 6.2 or newer toolchain and raise your deployment target to at least macOS 12 / iOS 15.
- Callbacks replaced by
asyncmethods (#4). Thecompletion:closures are gone. Upgrade: replacefms.query(q) { response in let rs = try response() … }withlet rs = try await fms.query(q), and likewise for the other three methods. - Perfect-CURL removed (#4), and with it PerfectLib, which came in through Perfect-CURL. Upgrade: drop Perfect-CURL from your own manifest if you listed it only for this package, and add PerfectLib yourself if your code imported it without depending on it. On Linux, FoundationNetworking still links libcurl itself.
- 5-second default inactivity timeout (#4). Each request sets
URLRequest.timeoutIntervalto 5 seconds; 3.0.1 set no timeout of its own. That is an inactivity timeout: the request fails if no data arrives for 5 seconds, which in practice means waiting for the first byte, while a response that keeps arriving can take longer in total. Upgrade: for servers, large finds or scripted queries that are slow to start responding, create theFileMakerServerwith a longerdefaultTimeout:. The methods take no per-call timeout, so use a secondFileMakerServervalue for the slow calls if you want to keep the short default elsewhere. Connection: closeon every request (#4). The header asks the server to close the connection after its response (URLSession doesn't close the socket itself), so connections aren't kept alive for reuse and the Web Publishing Engine shouldn't keep idle client sessions open. Upgrade: nothing; expect one TCP (and TLS) handshake per request.- Stricter percent-encoding (#4). Database, layout, field, script and sort names and query values are encoded with an allow-list of
A-Z a-z 0-9 - . _ ~. 3.0.1 used PerfectLib'sstringByEncodingURL, which left= * & ! ( ) ; ' , / ? @unescaped, so a search value containing&could add query directives. Compound-query=expressions now percent-encode their parentheses. Operators are only encoded differently, not in effect:<and>are now sent literally where 3.0.1 encoded them, which decodes to the same thing. Upgrade: nothing for normal use; if you pre-escaped values yourself, stop, or they will be encoded twice. - Credentials over plain HTTP are logged (#4). With a user name set and TLS off (
useTLSunset and port not 443), each request writes a warning to standard error. Requests still go out. Upgrade: setuseTLS: trueor use port 443, or passuseTLS: falseknowingly and accept the warning. FMPQueryFieldis@unchecked Sendable(#4) because itsvalueisAny. Upgrade: pass only strings and numbers as values.
Fixes
- #4: Query-injection hole in the percent-encoder closed (strict allow-list encoding).
- #4: Requests time out after 5 seconds without data by default and ask the server to close the connection, after live use showed Web Publishing Engine sessions building up under crawl-style load. Queries stay
POSTwith the query in the body, so query values don't end up in URL logs. - Release prep: the seven live-server tests used to return early and count as passes without a server; they now show as skipped.
- Release prep: README corrections. It said Perfect-XML parses
FMPXMLLAYOUTresponses while also saying that grammar is unimplemented. Every request uses thefmresultsetgrammar:layoutInforeads field names, result types and portal fields from its metadata, andFMPXMLLAYOUTandFMPXMLRESULTare not implemented. It also called Linux unverified. - Release prep:
defaultTimeout's documentation described a per-calltimeout:parameter that doesn't exist and didn't say it is an inactivity timeout; corrected. The operator comments no longer claim 3.0.1's operators were double-encoded or broken. - Release prep: the offline test mocks used
type="text", but the code reads a field's data type fromresult=, so field typing was untested; mocks now match FileMaker's output.
Upgrade notes
- Point your dependency at
from: "4.0.0"and build with Swift 6.2 or newer; raise your deployment target to macOS 12 / iOS 15. This also brings in Perfect-XML 4.0.0. - Convert each callback call to
try await, inside anasynccontext. - Remove Perfect-CURL from your manifest if it was there only for this package.
- Decide on a timeout: 5 seconds without data is short for big finds or scripted queries that are slow to start responding.
- Check TLS: set
useTLS:explicitly if your server uses HTTPS on a port other than 443. - If you escaped field values yourself before passing them in, stop.
Legacy
The pre-Swift-6 code is preserved on the legacy branch, which points at the same commit as the 3.0.1 tag. Stay on 3.0.1 if you can't move to Swift 6.2 yet.