Repository navigation
Releases: gfreezy/SwiftStore
Release list
6.3.1
Fix a CloudKit synchronization crash during error recovery. Cancellation now runs in a detached Task so it does not inherit the CKSyncEngine delegate callback context. Attachment cleanup still runs after cancellation completes.
The existing release workflow passed CloudKit synchronization checks, built the macOS arm64 CLI, and downloaded and verified the published archive and SHA256 checksum. No additional local tests or builds were run after release authorization.
Full Changelog: 6.3.0...6.3.1
6.3.0
Full-text relevance ordering
search and matching now accept orderByRank: true on both entities and Query:
let articles = try Article.search("database indexing", orderByRank: true)
.order(by: \.createdAt, ascending: false)
.limit(20)
.all(connection)The default remains false. When enabled, FTS5 rank sorts ascending before ordinary ordering; existing and subsequent .order(by:) calls break relevance ties. If multiple searches enable rank ordering, the last rank takes precedence.
Rank queries use the library's identity mapping and bound parameters, supporting UUID and composite keys, sparse business rowids, named indexes, ordinary filters, projections, and pagination. Configured FTS rank functions are respected. Count, aggregate, and batch-write behavior remains unchanged.
Rank is evaluated for matching candidates before the outer sort and pagination; this API does not use FTS5's direct ORDER BY rank LIMIT optimization.
Validation
Before the release request, 46 related tests passed, including six new rank tests. No local tests, builds, linting, or other validation were run for this release. The release workflow verifies CloudKit synchronization, builds the macOS arm64 CLI, and downloads and verifies its archive and SHA256SUMS.
Full Changelog: 6.2.1...6.3.0
6.2.1
JSON array full-text indexing
#FullTextIndex now supports array fields with .each, including multiple text fields, optional arrays and nested arrays:
#FullTextIndex<Self>(
\.title,
.each(\.chapters, fields: \.title,
.each(\.paragraphs, fields: \.text, \.translation)),
name: "book_search"
)Each text leaf has an independent search column. Array order is preserved; unselected metadata and missing/null values are excluded. Original JSON remains unchanged, and no persisted search-text field is required.
SwiftStore registers the versioned swiftstore_fts_text_v1 scalar function on every connection. Existing external-content views and triggers use it for local/remote writes, rebuilds and integrity checks. Migration generation and checking understand the new array metadata. Adding or changing an index still requires a new migration; existing snapshots remain compatible.
Ordinary SQLite tools can read the original business tables, but operations involving the new views or triggers require the same function to be registered.
Validation
The implementation passed 373 Swift Testing tests and 46 XCTest tests before release. The release workflow separately verifies CloudKit synchronization, builds the macOS arm64 CLI, and downloads and verifies the published archive and SHA256SUMS.
Full Changelog: 6.1.3...6.2.1
Includes a macro code-generation type-checking compatibility fix for the release CI compiler. The 6.2.0 CLI release was not published because its CI build failed.
6.1.3
6.0.0
SwiftStore now resolves query columns from metadata generated by @Entity, fixing key-path queries that could produce invalid SQL in optimized builds. The existing filter(\.id == id), ordering, projection and update DSL remains unchanged.
Changes:
- Generate explicit property-to-column mappings from the same declarations as the schema and SQLite codec, without parsing key-path debug descriptions.
- Use declared identity columns for CRUD, including single-field
#SyncKeyaliases and composite identities. - Reject unmapped query properties before executing SQL.
- Keep single-key batch queries as
INexpressions. - Preserve the encoded Swift property names in nested JSON paths for both ordinary and full-text indexes; SQL column names remain snake_case.
Breaking API changes:
- Direct calls to
columnName(for:)andColumn.namenow requiretry. - Handwritten
EntityProtocolimplementations must providecolumnName(for:)for key-path queries; composite identities also requiresqliteIdentityValues(for:)insyncKeyColumnsorder. - Previously generated nested JSON indexes using snake_case JSON paths are not automatically migrated. This release adds no compatibility fallback.
Validation completed during implementation: full Debug tests and focused Release regression tests, including generic ID access, composite keys, invalid mappings, bulk ID queries and camelCase JSON index updates. The release workflow builds the macOS arm64 CLI and verifies the packaged and published artifacts.
5.1.2
5.1.1
5.1.0
Adds @Entity(sync: false) for local-only entities in a database that also contains synchronized entities.
- Local-only entities retain normal schema migrations, CRUD, writable field requirements, and shared transactions. Writable entities participate in sync by default; readonly entities do not.
- Change tracking and initial snapshots exclude local-only entities.
- Uploads skip existing logs for explicitly local-only entities. The upload cursor advances only through a continuous prefix of skipped or confirmed events, without crossing an unconfirmed synchronized event. Entirely local batches are confirmed locally without empty CloudKit uploads.
- Downloads ignore explicitly local-only entities and commit the page checkpoint normally. Unknown entity types and invalid synchronized records still block progress.
- Sync participation is fixed for a manager lifetime. The option does not delete existing cloud records or define a resynchronization policy for re-enabling an entity.
Validation: 406 tests passed after a clean build during implementation, with no compiler warnings. Local tests, builds, formatting and lint checks were skipped for this release as requested. The release workflow builds, smoke-tests, packages and verifies the published macOS arm64 CLI.
5.0.0
Embedded raw-value types now use their RawValue SQLite codec for storage and queries. String enums store plain TEXT, integer enums use INTEGER, and floating-point enums use REAL. This release also removes legacy sync migration APIs and compatibility code.
Breaking changes
- Existing business databases containing JSON-encoded enum columns require an application-owned versioned migration before using the new codec. String enums need JSON unwrapping; numeric enums also need the matching INTEGER or REAL column affinity. Nested JSON documents retain their Codable format.
- Removed
LegacySyncMigration, theSyncOptions.migrationargument, legacy sync file import/detection, and sync migration markers. Legacy sync storage is not migrated. - Source-based schema extraction requires referenced custom codec declarations in its input files. Unsupported or unresolved storage metadata produces a diagnostic instead of silently defaulting to TEXT.
Improvements
- RawValue delegation supports type aliases and custom SQLite codecs without an enum type-name whitelist.
- Raw-value query predicates support optional values, comparisons, membership, ranges, and SQL interpolation through protocol constraints. Explicit
SQLiteValueComparableconformance can use the default raw-value projection. - JSON storage metadata is independent of queryability. Custom column types and decoding follow codec metadata; scalar enum defaults no longer receive a JSON-object SQL default.
- Changelog operations use the shared
sqliteEncode()API.
Validation
Implementation validation included 401 passing tests before sync compatibility cleanup, followed by 61 passing focused sync/connection tests after cleanup. Local tests, builds, formatting, and lint checks were skipped for this release as requested. The release workflow builds, smoke-tests, packages, and verifies the published macOS arm64 CLI.
4.1.2
Adds ConnectionManager.performAdditionalSetup(connection:) throws for database setup using the managed writer connection.
- Runs after migration and change tracking start, inside a writer transaction.
- With sync configured, writes to registered entities and their changelog commit or roll back together.
- Keeps the asynchronous no-argument setup hook, which runs after database setup commits.
waitForMigration()and normal database operations wait for both hooks to succeed.- Documents idempotent seeding and verifies tracked inserts, reopening, local-only setup, and rollback.
Validation: 17 focused tests passed during implementation. Local tests, linting, and builds were skipped for this release as requested.