Skip to content

Add DataSync API - #264

Draft
jguz-pubnub wants to merge 10 commits into
masterfrom
feat/data-sync
Draft

jguz-pubnub wants to merge 10 commits into
masterfrom
feat/data-sync

Conversation

@jguz-pubnub

@jguz-pubnub jguz-pubnub commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

feat(data-sync): add DataSync API

Adds the pubnub.dataSync namespace with paged fetch, create, replace, update, and remove operations for entities, users, channels, memberships, and relationships. Object changes are delivered to subscribe listeners as PubNubDataSyncEvent, and DataSync subscribe targets support both base and projection subscriptions.

feat(access-manager): add DataSync token resources and create permission

Access Manager tokens now parse DataSync resource permissions and expose the new create permission alongside the existing ones.

feat(configuration): read the origin from the Info dictionary

PubNubConfiguration.init(bundle:) accepts an originAt: plist key, defaulting to PubNubOrigin.

refactor(subscribe): free the word "entity" for Data Sync

entity now means a DataSync record, so the subscribe API uses target instead; the subscribe target types drop the Representation suffix, and Subscription / SubscriptionSet are created only through the PubNub factory methods.

BREAKING CHANGES: subscribe entity types are renamed and entities: becomes targets:.

refactor(subscribe): unify the legacy listener on PubNubEvent

The legacy SubscriptionListener emits the same PubNubEvent type as the modern listener API, and the catch-all event callbacks are deprecated in favor of the granular per-type ones.

BREAKING CHANGES: the legacy SubscriptionListener now emits PubNubEvent instead of SubscriptionEvent

BREAKING CHANGES: didReceiveSubscriptionChange, SubscribeResponseHeader, and the subscriptionChanged / responseReceived cases of PubNubSubscribeEvent are removed.

refactor(subscribe): make listener configuration immutable

BaseSubscriptionListener.queue and supressCancellationErrors are now passed to the initializer, removing a data race when they were mutated on a live listener.

BREAKING CHANGES: listener queue and supressCancellationErrors are now set at construction only.

refactor(build): deintegrate the VSP modules from Package.swift

PubNubUser, PubNubSpace, and PubNubMembership are no longer built or distributed via SPM, though their sources remain in the repository.

BREAKING CHANGES: PubNubUser, PubNubSpace, and PubNubMembership SPM products are no longer available.

fix(json): decode date-only values

yyyy-MM-dd values now decode as dates, as an ISO 8601 fallback.

fix(json): correct AnyJSON dictionary equality

Fixes an issue where a dictionary compared equal to any superset of itself, because only the left operand's keys were checked. Key counts are now compared first.

fix(subscribe): drop unrecognized message types

The SDK now skips subscribe messages whose e value it does not recognize. Messages that omit e preserve current inference behavior, while malformed entries no longer disrupt delivery of the remaining batch.

- Add DataSync routers for channels, users, entities, memberships, and relationships
- Extend `HTTPRouter` with the `Data Sync` service and DataSync-specific query keys
- Add error descriptions for empty DataSync ids, entity/relationship classes, and patch operations
- Only set the default `Content-Type` header when the request doesn't already provide one
- Add unit test coverage for the new DataSync routers
* Add DataSync PAM token resources and create permission
* Wrap DataSync create/replace bodies in data envelope and expose entity_class_level
- Recognize the `e: 5` DataSync wire type, which previously fell back to  `.message` and silently surfaced DataSync changes as plain messages
- Add `PubNubDataSyncEvent` with entity/relationship created, updated and  deleted cases, delivered through the new `onDataSync` closure
- Add `PubNubDataSyncEntity` and `PubNubDataSyncRelationship` models, plus `PubNubDataSyncRemovedObject` for delete events that carry identity only
- Support both listener generations: `onDataSync` on `EventListenerInterface` and `didReceiveDataSyncEvent` on the legacy `SubscriptionListener`
- Parse the level-encoded `className` (`::name`, `:name:`, `name::`) into a name plus `PubNubDataSyncClassLevel`
- Decode date-only (`yyyy-MM-dd`) timestamps by adding `iso8601_dateOnly` as a further fallback after the full ISO 8601 and no-milliseconds formatters, so DataSync fields such as `expiresAt` parse correctly
- Fix `AnyJSON` dictionary equality, which compared subsets and so was asymmetric and inconsistent with `hash(into:)`
- Split `SubscribeRouterTests` into per-feature extensions to stay within the file-length limit
- Add the optional `entity_class` filter to the DataSync user and channel list routers, matching `GET /users` and `GET /channels` in `v4-data.yaml`
- `DataSyncAPI`: CRUD for entities, users, channels, relationships, memberships
- Models: `PubNubDataSyncEntity`, `User`, `Channel`, `Relationship`, `Membership`, `PubNubDataSyncPage`
- JSON Patch (RFC 6902) support for `update*` methods
- PubNubConfiguration`: new `originAt:` plist-key parameter
- Snippets per DataSync class + 11.0 migration guide section
- Unit and integration tests, plus a new `PubNubDataSyncTests` test suite
- Deintegrate VSP modules from `Package.swift` while preserving their source code
- Add KMP bindings for DataSync

Subscribe entities are renamed alongside: 

- Drop the `Representation` suffix (`Channel`, `ChannelGroup`, `UserMetadata`, `ChannelMetadata`)
- Fold `Subscriber` into `Subscribable`
- Rename `SubscribableType` to `SubscribeTarget`
- Move the `PubNub` factories from `EntityCreator` into `Subscribable+PubNub`.
`entity` now means a DataSync record, so the subscribe API stops using the word and DataSync drops redundant prefixes.

**Subscribe**
- `Subscription.entity` → internal `target`; `pubnub.subscription(entities:)` → `subscription(targets:)`
- `Subscription` / `SubscriptionSet` initializers are no longer public — use the `PubNub` factory methods
- `Subscribable` subclasses now provide identifiers through `SubscriptionTopology`
- Added DataSync subscribables
- Added `PubNub` factories such as `dataSyncUser(_:)` and `dataSyncEntity(_:)`
- Data Sync subscribables support `.subscription()` and `.subscription(projection:)`
- Base and `default` projection subscriptions use the resource ID as the channel
- Custom projections derive `__<projection>__<resource_id>`

**DataSync**
- `entityClass` / `entityClassVersion` / `entityClassLevel` → `className` / `classVersion` / `classLevel`
- `relationshipClass` / `relationshipClassVersion` → `className` / `classVersion`
- `className` now precedes `classVersion` on users and channels
- `classVersion` follows `className` on relationships
- User/Channel APIs now return the shared `PubNubDataSyncEntity` model instead of duplicate user/channel models.
- Memberships reveal their `PubNubDataSyncRelationship`, mapping channel and user IDs to entityAId/entityBId
- Deleted relationships use `PubNubDataSyncRemovedRelationship` instead of the entity deletion model
- `PubNubDataSyncRelationship.classLevel` removed — relationship classes cannot be extended
- KMP now mirrors the Swift signatures parameter-for-parameter
- `filter` → `filter_fast` (`filterFast:`), 
-  `filter_advanced` → `filter` (`filter:`)
-  `expiresAt` becomes non-optional
- enable DataSync integration tests
- add scripts to show how DataSync classes that integration tests rely on were created
@pubnub pubnub deleted a comment from coderabbitai Bot Sep 4, 2026
@jguz-pubnub jguz-pubnub changed the title Add Data Sync API Add DataSync API Sep 4, 2026
@pubnub pubnub deleted a comment from coderabbitai Bot Sep 7, 2026
@pubnub pubnub deleted a comment from coderabbitai Bot Sep 11, 2026
@pubnub pubnub deleted a comment from coderabbitai Bot Sep 13, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant