Skip to content

improvement(client-presence): Json in-out improvements #24772

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jun 9, 2025

Conversation

jason-ha
Copy link
Contributor

@jason-ha jason-ha commented Jun 6, 2025

Externally:

Internally:

  • use OpaqueJsonDeserialized as stored and message type for generic (unknown) cases. system:presence workspace data values are kept exact under interface ConnectionValueState.
  • add helpers for needed conversions

Co-authored-by: Tyler Butler tylerbu@microsoft.com

jason-ha added 12 commits June 2, 2025 15:07
Simplify internal unknown (generic) customer data that must be Json serializable using Opaque Json types

At boundaries of API ins and outs, Json filtered types are cast to/from Opaque Json types. See new helpers:
  - `fullySerializableToOpaqueJson`
  - `asDeserializedJson`
  - `asDeeplyReadonlyDeserializedJson`

Notifications utilities are updated and removal of `string &` for `NotificationListeners` allowed clean up of `@ts-ignore-error`. `NotificationsManagerImpl`'s `emit` implementation now just types `name` to `string`.'
…lizable

as we are confident that is sufficient. See microsoft#24751.

Update opaque cast helper to only require `JsonSerializable`.
Note: `testUtils.ts`'s `prepareConnectedPresence` has error where an `InboundClientJoinMessage` is supposed to satisfy `OutboundClientJoinMessage`.
after ignoring remaining type issue in presenceDatastoreManager.ts
`PresenceDatastore` does not satisfy `DatastoreMessageContent`
 - `PresenceDatastore` -> `DatastoreMessageContent`
 - `InboundClientJoinMessage` -> `OutboundClientJoinMessage`
- `serializableToOpaqueJson` -> `toOpaqueJson`
- `asDeserializedJson` -> `revealOpaqueJson`
@Copilot Copilot AI review requested due to automatic review settings June 6, 2025 06:50
@jason-ha jason-ha requested a review from a team as a code owner June 6, 2025 06:50
@jason-ha jason-ha requested review from tylerbutler and WillieHabi and removed request for Copilot June 6, 2025 06:50
@github-actions github-actions bot added area: framework Framework is a tag for issues involving the developer framework. Eg Aqueduct public api change Changes to a public API base: main PRs targeted against main branch labels Jun 6, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR improves JSON input/output handling for client-presence by simplifying the externally required data to JsonSerializable and switching internal handling to use OpaqueJsonDeserialized. In addition, the changes update tests and internal helpers to consistently wrap and unwrap JSON values using the new opaque JSON utilities.

  • Removed the redundant JsonDeserialized requirement in initial values.
  • Updated tests to wrap literal JSON objects with toOpaqueJson.
  • Refactored multiple components (including notifications, value managers, and internal utilities) to use opaque JSON conversion and reveal functions.

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/framework/presence/src/test/presenceStates.spec.ts Updated the createValueManager signature to remove the redundant JsonDeserialized.
packages/framework/presence/src/test/presenceDatastoreManager.spec.ts Replaced raw JSON objects with toOpaqueJson wrappers in test cases.
packages/framework/presence/src/test/notificationsManager.spec.ts Updated notification test values to use opaque JSON wrapping.
packages/framework/presence/src/test/latestValueManager.spec.ts Added an extra test for inferred nullable types and adjusted opaque JSON usage.
packages/framework/presence/src/test/latestMapValueManager.spec.ts Renamed a key from "true" to "boolean" and used toOpaqueJson consistently.
packages/framework/presence/src/test/batching.spec.ts Replaced inline JSON values with toOpaqueJson wrappers for consistency.
packages/framework/presence/src/systemWorkspace.ts Refactored state update handling with revealOpaqueJson for JSON unwrapping.
packages/framework/presence/src/notificationsManager.ts Converted notification payload values using toOpaqueJson and revealOpaqueJson.
packages/framework/presence/src/latestValueManager.ts Adjusted local value setter to wrap the value with toOpaqueJson and use a new shallow clone helper.
packages/framework/presence/src/latestMapValueManager.ts Applied opaque JSON conversion in set and emit methods.
packages/framework/presence/src/internalUtils.ts Introduced new helper functions (toOpaqueJson, revealOpaqueJson, asDeeplyReadonlyDeserializedJson) for opaque JSON conversion.
packages/framework/presence/api-report/* Updated API types and documentation to reflect the new opaque JSON conventions.
Comments suppressed due to low confidence (4)

packages/framework/presence/src/test/latestMapValueManager.spec.ts:204

  • The key has been renamed from 'true' to 'boolean'; verify that no consumer of this test data relies on the previous key naming to avoid breaking changes.
boolean: true,

packages/framework/presence/src/notificationsManager.ts:247

  • The use of revealOpaqueJson to unwrap the notification update payload is a key design change. Please ensure that the structure of the unwrapped value matches the expected notification format throughout the system.
const value = revealOpaqueJson(updateValue.value);

packages/framework/presence/src/test/presenceStates.spec.ts:46

  • The change to remove JsonDeserialized from the initial value type is clear; please ensure that downstream code expects only JsonSerializable without relying on deserialized data.
initial: JsonSerializable<T>,

packages/framework/presence/src/latestValueManager.ts:128

  • Using toOpaqueJson to wrap the value in the local setter enforces opaque JSON conversion. Confirm that this change aligns with the expected handling of JSON values in all related components.
this.value.value = toOpaqueJson<T>(value);

@jason-ha jason-ha force-pushed the presence/use-opaque-json branch from 200091e to b6da44a Compare June 6, 2025 07:24
Copy link
Member

@tylerbutler tylerbutler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of docs nits. Thanks for pulling this together.

@@ -26,17 +23,35 @@ export namespace InternalTypes {
}

/**
* `ValueRequiredState` is used to represent a state that may have a value.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong type used here. I also generally recommend against repeating the name of the item in its docs.

Suggested change
* `ValueRequiredState` is used to represent a state that may have a value.
* Represents a state that may have a value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the name is continued trial of addressing the style/format question from end of May. (Awaiting yours and @WayneFerrao's comment) See last message: #24718 (comment)
I think we are likely to get the name wrong like this; so I think we don't have it. Full sentences? Use period even if not?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replied in the other PR. Sorry, never saw that comment.

Copy link
Contributor

@Josmithr Josmithr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some nitpicks, but overall looks good to me.

Copy link
Contributor

github-actions bot commented Jun 9, 2025

🔗 No broken links found! ✅

Your attention to detail is admirable.

linkcheck output


> fluid-framework-docs-site@0.0.0 ci:check-links /home/runner/work/FluidFramework/FluidFramework/docs
> start-server-and-test "npm run serve -- --no-open" 3000 check-links

1: starting server using command "npm run serve -- --no-open"
and when url "[ 'http://127.0.0.1:3000' ]" is responding with HTTP status code 200
running tests using command "npm run check-links"


> fluid-framework-docs-site@0.0.0 serve
> docusaurus serve --no-open

[SUCCESS] Serving "build" directory at: http://localhost:3000/

> fluid-framework-docs-site@0.0.0 check-links
> linkcheck http://localhost:3000 --skip-file skipped-urls.txt

Crawling...

Stats:
  222981 links
    1707 destination URLs
    1939 URLs ignored
       0 warnings
       0 errors


@jason-ha jason-ha enabled auto-merge (squash) June 9, 2025 20:09
@jason-ha jason-ha merged commit 03152a6 into microsoft:main Jun 9, 2025
35 checks passed
@jason-ha jason-ha deleted the presence/use-opaque-json branch June 9, 2025 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: framework Framework is a tag for issues involving the developer framework. Eg Aqueduct base: main PRs targeted against main branch public api change Changes to a public API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants