[Feature] Path based LiveObjects Implementation - #2230
Draft
sacOO7 wants to merge 25 commits into
Draft
Conversation
sacOO7
commented
Jul 24, 2026
Contributor
- PathObject documentation -> https://ably.com/docs/liveobjects/concepts/path-object
- Public API doc -> PathObject based LiveObjects API
- PathObject spec -> https://sdk.ably.com/builds/ably/specification/main/objects-features/
Adds Scripts/import-repo-contents.sh, which extracts the tracked files of another git repository at a given commit into a directory of this repository. This will be used by upcoming commits that import the contents of the ably-cocoa-plugin-support and ably-liveobjects-swift-plugin repos into this repo (see AIT-1027). Putting the import behind a script keeps those commits reproducible: to swap in a newer version of an imported repo, drop the import commit, rerun the script at the new SHA, and recommit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This is the verbatim contents of the ably-cocoa-plugin-support repo [1] at commit a290b89, imported by running: Scripts/import-repo-contents.sh \ https://github.com/ably/ably-cocoa-plugin-support.git \ a290b89 \ PluginSupport No modifications have been made to the imported files; subsequent commits will integrate them into this repo. This is part of merging the plugin-support and LiveObjects repos into ably-cocoa (AIT-1027), so that there is a single repository for ably-cocoa and its plugins. The _AblyPluginSupportPrivate library, which exposes ably-cocoa private API to Ably-authored plugins, only needed to live in a separate repo while its consumers (ably-cocoa and the LiveObjects plugin) lived in separate repos; it now becomes an implementation detail of this repo. [1] https://github.com/ably/ably-cocoa-plugin-support Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pure renames, no content changes:
- PluginSupport/Sources/_AblyPluginSupportPrivate
-> Sources/_AblyPluginSupportPrivate
- PluginSupport/README.md
-> Sources/_AblyPluginSupportPrivate/README.md
This is where the _AblyPluginSupportPrivate target will live as an
ordinary target of the ably-cocoa package (a subsequent commit updates
Package.swift). The README will be revised for its new home in a later
commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Removes the remaining files imported from the ably-cocoa-plugin-support repo, which are superseded now that its source code is part of this repo: - PluginSupport/Package.swift: the library becomes a target of this package (next commit) rather than a package of its own - PluginSupport/LICENSE, PluginSupport/COPYRIGHT: this repo's LICENSE and COPYRIGHT (identical Apache 2.0 licence) now cover the code - PluginSupport/.gitignore: only ignored build artefacts of the standalone package (.build etc.), which this repo's .gitignore already covers Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the ably-cocoa-plugin-support package dependency with a target built from the sources imported in the preceding commits. The target is deliberately not vended as a product: it only ever existed to expose ably-cocoa private API to Ably-authored plugins, and its only consumers (ably-cocoa and the LiveObjects plugin, which a later commit brings into this repo) now live here. Note for the transition period: a dependency graph that contains both this version of ably-cocoa and the standalone LiveObjects plugin (which depends on the ably-cocoa-plugin-support package) will fail to resolve with a duplicate target name error, since both provide a target named _AblyPluginSupportPrivate. That combination could never work anyway; plugin users should migrate to the AblyLiveObjects product introduced later in this branch. A final release of the standalone plugin will cap its ably-cocoa dependency so that existing users' `swift package update` keeps resolving a working (old) pair. CocoaPods and Carthage are unaffected: plugin support is SPM-only (ABLY_SUPPORTS_PLUGINS is only defined in Package.swift), and neither the podspec nor the Xcode project referenced the removed package. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Needed so that the AblyLiveObjects target (added in a later commit) can use the Swift 6 language mode and internal imports, which require per-target .swiftLanguageMode settings (tools 6.0+). Consequences for users: - SPM consumers now need Xcode 16.3 or later (April 2025) to resolve this package. CocoaPods and Carthage consumers are unaffected (neither reads Package.swift). - This does not change the OS versions the SDK supports: the declared platforms are unchanged, and deployment-target support is a property of the consumer's Xcode, not of the tools version. Since 28 April 2026 the App Store requires apps to be built with Xcode 26 [1], so in practice App Store developers already exceed this requirement. - Consumers on older toolchains resolving with a `from:` range will stay pinned to the last tools-5.3 release (1.2.x) rather than failing, since SwiftPM excludes versions whose manifest requires newer tools. Escape hatch: if consumers who cannot upgrade Xcode (e.g. enterprise certificate distribution) report breakage, this is fixable in a patch release by renaming this manifest to Package@swift-6.1.swift and reintroducing a tools-5.3 Package.swift vending only the Ably product; SwiftPM serves each consumer the newest manifest their tools support. Mechanical changes required by the new tools version: - Test targets that predate the Swift 6 language mode (AblyTests, AblyTesting) explicitly opt in to .swiftLanguageMode(.v5), since tools 6.x defaults targets to the Swift 6 mode. - The UTS test target's unsafeFlags(["-swift-version", "6"]) workaround becomes a proper .swiftLanguageMode(.v6). - The deprecated .package(name:url:from:) dependency forms become .package(url:from:), which in turn requires the explicit .product(name:package:) form for cross-package target dependencies. [1] https://developer.apple.com/news/upcoming-requirements/?id=02032026a Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This is the verbatim contents of the ably-liveobjects-swift-plugin
repo [1] at commit a3bf63d, imported by running:
Scripts/import-repo-contents.sh \
https://github.com/ably/ably-liveobjects-swift-plugin.git \
a3bf63d697ebf8b1c0da6d6491df504728fa4c03 \
LiveObjects
No modifications have been made to the imported files; subsequent
commits integrate them into this repo. Two notes on the import
mechanics:
- The plugin repo's Tests/AblyLiveObjectsTests/ably-common submodule
is not imported (git archive emits submodules as empty directories).
A later commit points the affected test helper at this repo's
existing ably-common submodule instead.
- If a newer version of the plugin needs to be swapped in before this
branch lands, drop this commit, rerun the script at the new SHA and
recommit; the subsequent commits are either outside LiveObjects/,
small itemised deletions, or regenerated by script.
This is the main step of merging the LiveObjects plugin into
ably-cocoa (AIT-1027), giving a single repository for ably-cocoa and
its plugins, as with ably-js and ably-java. LiveObjects/ is the
permanent home of this code, not a staging area: the plugin's
development tooling, example app, docs and configuration continue to
live and work in this directory.
[1] https://github.com/ably/ably-liveobjects-swift-plugin
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The two preceding import commits are the only reason Scripts/import-repo-contents.sh existed, so remove it now that they are done; this repo has nothing left to import. The script remains available in the history at the import commits (whose messages reference it and describe how to rerun it), so the imports remain reproducible. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Removes files imported from the ably-liveobjects-swift-plugin repo that are superseded by their ably-cocoa equivalents: - LiveObjects/Package.swift, LiveObjects/Package.resolved: the AblyLiveObjects library becomes a product of this package (a later commit adds its targets to the root manifest); the BuildTool target gets its own nested package in a later commit - LiveObjects/.github/: the plugin's CI workflow; a later commit adds an equivalent workflow to this repo's .github/workflows - LiveObjects/.gitmodules: git only honours the repository-root .gitmodules, so this imported copy is inert; the submodule it described is not imported (see previous commit) - LiveObjects/LICENSE, LiveObjects/COPYRIGHT, LiveObjects/ MAINTAINERS.md: this repo's equivalents (identical Apache 2.0 licence) now cover the code Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Moves the plugin's BuildTool executable (imported two commits ago as
LiveObjects/Sources/BuildTool) into a standalone package at
LiveObjects/BuildTool, with a new manifest carrying over its
dependencies (swift-argument-parser, swift-async-algorithms, Table)
from the deleted plugin manifest. Its Xcode scheme moves alongside it.
Making it a separate package, rather than a target of the root
ably-cocoa package, keeps its dependencies out of the manifest that
ably-cocoa's consumers resolve. It is run from the LiveObjects
directory:
swift run --package-path BuildTool BuildTool <subcommand>
The move of the sources is a pure git rename; a later commit fixes the
path assumptions that no longer hold in its new home.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds Scripts/annotate-liveobjects-availability.py and applies it,
inserting
@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)
above all 222 top-level declarations in
LiveObjects/Sources/AblyLiveObjects. These are the platform versions
that the standalone plugin declared in its Package.swift.
This change is entirely script-generated, with no manual edits, so it
can be regenerated if the imported plugin sources are ever replaced
with a newer version (see the import commit).
Why this is needed: SwiftPM platform requirements are package-wide,
and ably-cocoa's (iOS 9 / macOS 10.11 / tvOS 10) are far below what
LiveObjects requires — its Swift concurrency usage alone needs
iOS 13 / macOS 10.15. Per-declaration availability is how a single
package hosts both: the compiler builds AblyLiveObjects at the
package's old deployment target and these annotations both satisfy
its availability checking and make consumers on older OS versions
guard their use of the LiveObjects API with #available.
The script is idempotent; CI will run it and fail on a non-empty diff
so that new declarations cannot be added without an annotation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The plugin repo had its own ably-common submodule, used for exactly one thing: the sandbox test helper reads test-app-setup.json from it when creating an Ably sandbox app for the integration tests. This repo already has an ably-common submodule (at Test/AblyTests/ably-common, used by AblyTests), and we do not want two. The helper now resolves the file via #filePath relative to the repo layout, instead of a bundle resource, because: - SwiftPM requires a target's resources to live inside the target's directory, and the submodule lives in another target's tree. - Symlinking it into this target's tree does not work: SwiftPM copies the symlink itself into the resource bundle, where it dangles. Note that the two repos' submodules pointed at different ably-common commits; this repo's pin is a descendant of the plugin's, so this is a fast-forward for the fixture. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the AblyLiveObjects target (the sources imported from the ably-liveobjects-swift-plugin repo), its test target, and a library product, to the root manifest. The target paths point into LiveObjects/. Users of the standalone plugin migrate by replacing their ably-liveobjects-swift-plugin package dependency with this package's AblyLiveObjects product; the module name and API are unchanged. The test target has no resources entry: the fixture that was a bundle resource in the plugin repo is loaded from the repo tree instead (see previous commit). Package.resolved is unchanged, since the LiveObjects library brings no new dependencies (its BuildTool development tool, which does have dependencies, is deliberately a separate nested package). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The plugin's Xcode workspace and shared scheme assumed the package manifest lived at the plugin repo root; the AblyLiveObjects targets are now part of the ably-cocoa package at this repo's root. So: - AblyLiveObjects.xcworkspace's package reference changes from "group:" to "group:..". - The shared AblyLiveObjects scheme (which carries the test action and its test-plan associations, used by BuildTool's xcodebuild invocations) moves to this repo's .swiftpm scheme directory — Xcode only discovers package schemes at the package root — with its test-plan references updated to container:LiveObjects/TestPlans/. - The AblyLiveObjects-Package scheme and the standalone package's workspace settings are removed as obsolete (the equivalent whole-package scheme now belongs to ably-cocoa). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The example app project declared a remote package dependency on swift-async-algorithms, but nothing in its code imports it. In the plugin repo this was harmless: BuildTool (a target of the plugin package) also depended on swift-async-algorithms, so it was part of the package's dependency graph anyway. In this repo, where BuildTool is a separate nested package, the example app's reference would be the only thing pulling swift-async-algorithms into the LiveObjects workspace's resolution, making that resolution a superset of the root package's dependency graph — which both defeats the lockfile consistency check that a later commit preserves, and causes Xcode to transiently rewrite the root Package.resolved with the extra pins. Also removes the example project's own workspace-scoped Package.resolved, whose only pins were this removed dependency and its transitive dependency. Verified by resolving the LiveObjects workspace (its resolution now matches the root package's dependency graph exactly) and building the example app for macOS via BuildTool. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BuildTool and the lint configuration assumed the LiveObjects directory was a repo/package root. It is still the working directory that BuildTool must be run from, but some of the things it deals with now live elsewhere: - Lint's swift-tools-version consistency check now reads the root ../Package.swift (which is what governs compilation of the LiveObjects sources); .swift-version stays in LiveObjects/ because SwiftFormat reads it from there. - Lint's lockfile comparison now compares the Xcode-managed workspace lockfile against the root ../Package.resolved. To make the two comparable (and to stop SwiftPM and Xcode disagreeing about the file's representation), the root Package.resolved is rewritten in the current lockfile format (version 3) with unchanged pins, and the workspace copy imported from the plugin repo is replaced with the Xcode-written equivalent for this package's dependency graph. - SwiftLint and Prettier now exclude BuildTool/.build, the nested BuildTool package's build directory, which contains dependency checkouts (previously the build directory was .build, which the configs already exclude). - The Secrets.swift file that BuildTool generates for example-app CI builds now ends with a newline, without which SwiftFormat fails a subsequent local lint run. Verified by running every lint step and BuildTool's generate-matrices, test-library and build-example-app subcommands against this layout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
xcodebuild compiles the AblyLiveObjectsTests target at (nearly) this package's declared platform floor: for iOS and tvOS destinations it raises the floor of 12 only as far as 13. The test code was written against the standalone plugin repo's floor of iOS/tvOS 14 — its xcodebuild test builds compiled at exactly that — and fails availability checking below it, since it freely uses the LiveObjects API, whose declarations are @available(iOS 14, tvOS 14, ...). The plugin repo never hit this, and `swift test` doesn't either (SwiftPM raises test targets' deployment target on macOS of its own accord), which is why it only surfaced in this repo's Xcode-based CI jobs. The test sources cannot simply be annotated the way the library sources are: the swift-testing @suite macro rejects types marked @available ("Attribute 'Suite' cannot be applied to this structure because it has been marked '@available(...)'"). So instead, BuildTool now passes deployment-target build-setting overrides of iOS/tvOS 14 — restoring the regime the test code was written for — to the xcodebuild invocations that compile or run the tests. Command-line build settings do apply to Swift package targets. Test code that needs newer OS versions than this continues to declare it with @available on the affected declarations (e.g. Subscriber.swift and the tests that use it, whose parameter packs in generic types need iOS/tvOS 17); the library's declared availability is still checked at the package floor by the SPM-based CI jobs. There is deliberately no macOS override: xcodebuild raises macOS test-bundle builds well above the package floor of its own accord (the test host has to run on the build machine), and the test code relies on this — Subscriber.swift's @available annotation names only iOS and tvOS, so its use of parameter packs (which need macOS 14) is unguarded on macOS. Verified by building and running the unit tests via BuildTool for tvOS simulator and macOS destinations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ports the ably-liveobjects-swift-plugin repo's Check workflow as .github/workflows/liveobjects.yaml, with the following adaptations for its new home (the core SDK's existing workflows are untouched; the check-spm workflow now inherently also builds the AblyLiveObjects product): - Steps run with LiveObjects/ as the working directory, and BuildTool is invoked via `swift run --package-path BuildTool BuildTool`. (The all-checks-completed marker job, which runs on ubuntu-latest without a checkout, overrides this default.) - The SPM job's `swift test` is filtered to the AblyLiveObjectsTests module; the rest of the package's tests belong to the core SDK's own workflows (though `swift test` builds all of the package's test targets, so -warnings-as-errors covers their compilation here too — note that the warning set is a property of this job's Xcode version, and newer toolchains may warn about things this one does not). - The docs job uses `xcodebuild docbuild` plus `docc process-archive transform-for-static-hosting` instead of the swift-docc-plugin package plugin, because the plugin would have to be a dependency of the root manifest, where ably-cocoa's consumers would resolve it. Uploads use this repo's AWS role. - New check-availability-annotations job enforcing the @available annotations on the LiveObjects sources (see Scripts/annotate-liveobjects-availability.py): the compiler checks public declarations via -require-explicit-availability, and the annotation script (which is idempotent) checks all top-level declarations by requiring a clean diff after running it. (-require-explicit-availability must be spelled as a frontend flag; the driver flag of the same name is a no-op.) The plugin repo's commented-out spec-coverage job has not been ported; it can be revisited when spec coverage tooling is picked up again. Note for branch protection: the all-checks-completed marker job of this workflow should be added to the required status checks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Root README: new LiveObjects section, including the experimental status note: breaking changes to the AblyLiveObjects API may occur in minor or patch releases without a major version bump, and ably-cocoa's semantic versioning guarantees apply only to the Ably product. - CHANGELOG: unreleased entry describing the migration from the standalone plugin package and the new Xcode 16.3+ requirement for SPM consumers, restating the semver exemption. - LiveObjects/README: the experimental warning gains the same semver wording; installation and releases now point at ably-cocoa; a note records the move from the ably-liveobjects-swift-plugin repo. - LiveObjects/CONTRIBUTING: commands updated for the new layout; the "developing ably-cocoa alongside this plugin" section is removed (the code now lives in the same repo and package, so there is nothing for it to say); the standalone release process is replaced by a pointer to ably-cocoa's. - LiveObjects/CLAUDE.md and root CLAUDE.md: build/test/lint commands updated for the new layout, and cross-references added. - Docs/plugins.md: _AblyPluginSupportPrivate and the LiveObjects plugin are now described at their in-repo locations, and ADR-128 is described as the original design, noting that its central premise for a separate plugin repository (package-wide OS requirements) turned out to be wrong. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
LiveObjects-only extraction of the path-based public API work (alternative to #2225, with the unrelated UTS test-infra and tooling changes dropped): - Namespace the internal ObjectMessage wire types under ProtocolTypes, freeing their plain names for the public API - Add the new path-based public surface (PathObject, Instance, RealtimeObject, value types, subscriptions) with Default* skeletons - Remove the old channel.objects proxy objects, PublicTypes, and the ported JS integration tests - Adapt the example app view models to the new API
The core SDK's sources live in Source/ (singular) while _AblyPluginSupportPrivate lived in Sources/ (plural), so both a Source and a Sources directory sat at the repo root — confusingly similar. This moves the _AblyPluginSupportPrivate target's directory up to the repo root, removing the Sources/ directory entirely so only Source/ remains. _AblyPluginSupportPrivate is an SPM-only target referenced by name, so the only path references are the target's own path: in Package.swift and one mention in Docs/plugins.md; both are updated here. No CocoaPods, Carthage, or Xcode-project changes are involved. A follow-up will move both _AblyPluginSupportPrivate and the core SDK to the idiomatic SwiftPM Sources/<TargetName>/ layout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move _AblyPluginSupportPrivate out of `Sources/` to the repo root
Merge LiveObjects plugin and plugin-support into ably-cocoa
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
github-actions
Bot
temporarily deployed
to
staging/pull/2230/AblyLiveObjects
July 24, 2026 11:45
Inactive
github-actions
Bot
temporarily deployed
to
staging/pull/2230/markdown-api-reference
July 24, 2026 11:49
Inactive
…lic-api Add path-based LiveObjects public API
github-actions
Bot
temporarily deployed
to
staging/pull/2230/AblyLiveObjects
July 28, 2026 10:13
Inactive
github-actions
Bot
temporarily deployed
to
staging/pull/2230/markdown-api-reference
July 28, 2026 10:16
Inactive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.