Skip to content

Conversation

@lawrence-forooghian
Copy link
Collaborator

@lawrence-forooghian lawrence-forooghian commented Aug 14, 2025

Note: This PR is based on top of #57; please review that one first.

Get rid of the annoying intermediate PrimitiveObjectValue, and add ExpressibleBy*Literal conformance.

Resolves #65.

Summary by CodeRabbit

  • New Features

    • LiveMapValue now uses direct cases (string, number, bool, data, JSON) with typed accessors.
    • Supports Swift literal initialization for map entries (strings, numbers, booleans, arrays, dictionaries).
  • Refactor

    • Removed the primitive wrapper type; simplified value pattern matching.
  • Documentation

    • Updated API docs and examples to reflect direct cases and literal usage.
  • Tests

    • Updated test suites to use direct variants and literals for map values; expectations adjusted accordingly.

@coderabbitai
Copy link

coderabbitai bot commented Aug 14, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The PR replaces the primitive wrapper model with direct enum cases for LiveMapValue across internal and public APIs. Internal conversion and serialization paths are updated accordingly. Public types gain literal conformances. Tests are adjusted to use direct cases and literals instead of the .primitive wrapper.

Changes

Cohort / File(s) Summary
Internal conversion
Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift
convertEntryToLiveMapValue now returns direct enum cases (.bool, .data, .number, .string, .jsonArray, .jsonObject) instead of .primitive-wrapped variants; objectId and tombstone handling unchanged.
Internal value modeling
Sources/AblyLiveObjects/Internal/InternalLiveMapValue.swift
Eliminates .primitive case; adds per-type cases; updates init(from public), accessors, Equatable, and toObjectData to match new cases; identity semantics for liveMap/liveCounter preserved.
Public proxy mapping
Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift
toPublic maps each internal primitive case directly to the corresponding public LiveMapValue case; liveMap/liveCounter mapping unchanged.
Public API types
Sources/AblyLiveObjects/Public/PublicTypes.swift
Removes PrimitiveObjectValue; refactors LiveMapValue to explicit cases; adds typed accessors and ExpressibleBy*Literal conformances; updates docs and equality; removes primitiveValue.
Tests updated to direct cases/literals
Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift, Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift, Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift, Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift, Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift
Replaces .primitive(...) usages with direct enum cases or Swift literals; updates expectations and pattern matching to new representation; minor data encoding adjustments where applicable.

Sequence Diagram(s)

sequenceDiagram
  actor Developer
  participant PublicAPI as LiveMapValue (Public)
  participant Internal as InternalLiveMapValue
  participant Protocol as ObjectData (Realtime)

  Developer->>PublicAPI: Provide value (literal or enum case)
  PublicAPI->>Internal: Map to InternalLiveMapValue (direct cases)
  Internal->>Protocol: Serialize via toObjectData (per-type mapping)
  Protocol-->>Internal: Encoded payload
  Internal-->>PublicAPI: Values decoded to internal cases
  PublicAPI-->>Developer: Expose as public LiveMapValue cases
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
Remove PrimitiveObjectValue type [#65, ECO-5525]
Refactor LiveMapValue to direct primitive cases [#65, ECO-5525]
Add ExpressibleBy*Literal conformances to LiveMapValue [#65, ECO-5525]
Update internal mappings and serialization to match new cases [#65, ECO-5525]

Possibly related PRs

Suggested reviewers

  • maratal

Poem

A nibble of code, a hop through the map,
I dropped my wrappers—no more nested wrap!
With literals bright, I bound and I leapt,
Keys hum with strings, and numbers are kept.
Thump goes the counter, bytes softly clap—
A swift little rabbit in a cleaner app. 🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 65-LiveMapValue-improvements

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@lawrence-forooghian lawrence-forooghian changed the base branch from main to ECO-5465-port-integration-tests August 14, 2025 16:10
@github-actions github-actions bot temporarily deployed to staging/pull/66/AblyLiveObjects August 14, 2025 16:11 Inactive
@lawrence-forooghian
Copy link
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Aug 14, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@umair-ably
Copy link
Collaborator

@coderabbitai full review

@coderabbitai
Copy link

coderabbitai bot commented Aug 15, 2025

✅ Actions performed

Full review triggered.

Copy link
Collaborator

@umair-ably umair-ably left a comment

Choose a reason for hiding this comment

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

simple enough change, don't feel like you have to wait for coderabbit but up to you

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (5)
Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift (1)

20-22: Clarify docstring about caching scope

The comment suggests the method “fetches the cached public object… creating a new public object if there isn't already one.” That caching behavior applies only to liveMap/liveCounter cases; primitives are value types returned directly with no caching. Consider tightening the wording to avoid implying caching for primitive cases.

Sources/AblyLiveObjects/Public/PublicTypes.swift (2)

84-106: Docblock is helpful; consider noting numeric precision and interpolation

Nice examples showcasing literal support. Two minor clarifications could prevent surprises:

  • Integer literals become .number(Double(value)), so very large integers may lose precision.
  • Interpolated strings like "value \(x)" won’t compile as LiveMapValue without ExpressibleByStringInterpolation conformance (see suggestion below).

If you want, I can add a short note to this doc section.


209-245: Add ExpressibleByStringInterpolation to support interpolated string literals

Interpolated strings currently won’t be accepted as LiveMapValue unless you add ExpressibleByStringInterpolation. Suggest adding:

 extension LiveMapValue: ExpressibleByStringLiteral {
   public init(stringLiteral value: String) {
     self = .string(value)
   }
 }
+
+extension LiveMapValue: ExpressibleByStringInterpolation {
+  public init(stringInterpolation: DefaultStringInterpolation) {
+    self = .string(String(stringInterpolation: stringInterpolation))
+  }
+}
Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift (2)

145-150: Nit: remove unnecessary try around Dictionary(uniqueKeysWithValues:)

Dictionary(uniqueKeysWithValues:) is non-throwing, so the try is redundant.

-        #expect(
-            try Dictionary(uniqueKeysWithValues: map.entries) == [
+        #expect(
+            Dictionary(uniqueKeysWithValues: map.entries) == [
                 "boolKey": true,
                 "numberKey": 10,
             ],
         )

182-186: Nit: remove unnecessary try in the final entries assertion

Same as earlier, this construction doesn’t throw.

-        #expect(
-            try Dictionary(uniqueKeysWithValues: map.entries) == [
+        #expect(
+            Dictionary(uniqueKeysWithValues: map.entries) == [
                 "numberKey": 10,
                 "counterKey": .liveCounter(counter),
             ],
         )
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c39d55f and 46de61a.

📒 Files selected for processing (9)
  • Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift (1 hunks)
  • Sources/AblyLiveObjects/Internal/InternalLiveMapValue.swift (4 hunks)
  • Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift (1 hunks)
  • Sources/AblyLiveObjects/Public/PublicTypes.swift (3 hunks)
  • Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift (3 hunks)
  • Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift (3 hunks)
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift (4 hunks)
  • Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift (9 hunks)
  • Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-07-29T08:07:47.875Z
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/swift.mdc:0-0
Timestamp: 2025-07-29T08:07:47.875Z
Learning: Applies to AblyLiveObjects/**/!(*Test|*Tests).swift : When importing the Ably module inside the AblyLiveObjects library code (non-test code), use `import Ably`.

Applied to files:

  • Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
  • Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift
📚 Learning: 2025-07-29T08:07:47.875Z
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/swift.mdc:0-0
Timestamp: 2025-07-29T08:07:47.875Z
Learning: Applies to AblyLiveObjects/**/!(*Test|*Tests).swift : When importing the AblyPlugin module inside the AblyLiveObjects library code (non-test code), use `internal import AblyPlugin`.

Applied to files:

  • Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
📚 Learning: 2025-07-29T08:07:58.385Z
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-29T08:07:58.385Z
Learning: Applies to **/Tests/**/*.swift : When you need to import the following modules in the tests, do so in the following way: Ably: use `import Ably`; AblyLiveObjects: use `testable import AblyLiveObjects`; AblyPlugin: use `import AblyPlugin`; do not do `internal import`.

Applied to files:

  • Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift
  • Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift
📚 Learning: 2025-07-29T08:07:47.875Z
Learnt from: CR
PR: ably/ably-cocoa-liveobjects-plugin#0
File: .cursor/rules/swift.mdc:0-0
Timestamp: 2025-07-29T08:07:47.875Z
Learning: Applies to **/*.swift : When writing JSONValue or WireValue types, favour using the literal syntax enabled by their conformance to the `ExpressibleBy*Literal` protocols where possible.

Applied to files:

  • Sources/AblyLiveObjects/Public/PublicTypes.swift
🧬 Code Graph Analysis (6)
Sources/AblyLiveObjects/Internal/InternalLiveMapValue.swift (1)
Sources/AblyLiveObjects/Public/PublicTypes.swift (1)
  • lhs (185-206)
Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift (2)
Sources/AblyLiveObjects/Utility/ExtendedJSONValue.swift (1)
  • map (78-99)
Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift (2)
  • entries (124-128)
  • entries (840-856)
Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift (2)
Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift (2)
  • entries (124-128)
  • entries (840-856)
Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift (2)
  • createMap (38-50)
  • createMap (52-63)
Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift (2)
Sources/AblyLiveObjects/Utility/ExtendedJSONValue.swift (1)
  • map (78-99)
Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift (1)
  • set (78-82)
Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift (4)
Sources/AblyLiveObjects/Utility/ExtendedJSONValue.swift (1)
  • map (78-99)
Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift (2)
  • createMap (38-50)
  • createMap (52-63)
Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift (2)
  • entries (124-128)
  • entries (840-856)
Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift (1)
  • set (78-82)
Sources/AblyLiveObjects/Public/PublicTypes.swift (1)
Sources/AblyLiveObjects/Internal/InternalLiveMapValue.swift (1)
  • lhs (143-164)
🔇 Additional comments (34)
Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift (1)

23-34: Direct primitive mappings look correct

The switch now cleanly maps each internal primitive to the corresponding public LiveMapValue case. This aligns with the removal of the wrapper and keeps bridging straightforward.

Sources/AblyLiveObjects/Public/PublicTypes.swift (4)

107-116: Enum case split is a solid improvement

Explicit per-type cases greatly simplify usage, pattern matching, and docs. This also makes the public surface consistent with internal representation.


135-181: Convenience getters are clear and symmetric

The accessors cover all primitive cases and the object cases already have their dedicated getters above. This is tidy and discoverable.


185-206: Equatable semantics are sensible

  • Value equality for primitives and JSON containers.
  • Identity for liveMap/liveCounter.
    This mirrors the internal equality and avoids expensive deep object comparisons.

107-116: No lingering references to PrimitiveObjectValue found

I searched the repo with ripgrep for \bPrimitiveObjectValue\b and \.primitive\s*\( — no matches were returned.

No action required.

Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift (2)

140-150: Good adoption of literal conformances in map creation and assertions

Using true and 10 directly keeps tests concise and validates the new API surface.


164-169: Assertions correctly reflect mixed object/primitive entries

The expected dictionary combining literals and .liveCounter is a nice end-to-end check of both literal support and object identity.

Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift (2)

889-906: Primitive mapping to internal variants looks correct and ordered per spec

  • .bool(boolean) before other types
  • .data(bytes) for binary
  • .number(number.doubleValue) for numeric
  • .string(string) for string

The order matches the RTLM5d2b–e guidance and aligns with the new internal value cases.


909-916: JSON mapping matches the new cases; confirm null handling

Switching .array to .jsonArray and .object to .jsonObject is consistent. One question: if json could ever be null, we currently drop to nil (no value). If that’s intentional under the current spec gap (TODO link), all good—just noting the behavior so it’s explicit in tests/specs later.

Tests/AblyLiveObjectsTests/ObjectCreationHelpersTests.swift (1)

39-49: Tests updated cleanly to per-type cases

Replacing .primitive(...) with .jsonArray, .jsonObject, .string, .number, .bool, and .data directly is clear and verifies the new construction paths end-to-end.

Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift (4)

1051-1051: Good migration to direct InternalLiveMapValue case

Using .string("testValue") directly aligns with the removal of the primitive wrapper and keeps the test intent clear.


1081-1081: LGTM: direct string value in entries

Switching to .string("stringValue") is consistent with the new API surface and the expected wire format.


1101-1101: Expectation matches updated internal data model

Comparing against InternalObjectsMapEntry(ObjectData(string:)) is the right assertion after the model change.


1159-1159: LGTM: createMap uses new value shape

Passing ["testKey": .string("testValue")] validates the new entry encoding path end-to-end.

Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift (5)

1240-1240: LGTM: invalid state test uses direct string value

This keeps the test concise and correctly targets the state validation without the wrapper indirection.


1267-1277: Parametrized value coverage updated correctly

Covering jsonArray, jsonObject, string, number, bool, and data via direct cases mirrors the internal/public enum changes and exercises the ObjectData mapping thoroughly.


1319-1321: LGTM: publish-failure path uses direct string

The change preserves the failure semantics while matching the new value shape.


2558-2570: Switching on direct cases simplifies assertions

Pattern-matching on .data, .string, .number, .bool reads cleaner and avoids nesting. This is a good update for readability.


2950-2966: CreateMap primitive verification updated correctly

Validations against .data/.string/.number/.bool are accurate given the new API; also the explicit guard for jsonArray/jsonObject not being in the primitive fixtures is appropriate.

Sources/AblyLiveObjects/Internal/InternalLiveMapValue.swift (6)

5-10: Solid enum shape replacing the primitive wrapper

Introducing explicit cases for string/number/bool/data/jsonArray/jsonObject removes ambiguity and makes both equality and serialization straightforward.


21-32: Bridging from public LiveMapValue is correct and exhaustive

Each public case maps 1:1 to the corresponding internal case. This keeps PublicDefaultLiveMap/PublicDefaultRealtimeObjects bridges simple and reliable.


54-65: Realtime protocol mapping is accurate

  • bool -> boolean
  • data -> bytes
  • number -> NSNumber(value:)
  • string -> string
  • jsonArray -> json.array
  • jsonObject -> json.object

These match the wire schema expectations for ObjectsMapOp data.


93-139: Convenience accessors add clarity

Per-type getters make tests and internal call sites much more readable than interrogating a single primitive wrapper.


145-163: Equatable semantics match public type and identity for live objects

Value cases compare by content; liveMap/liveCounter compare by identity. This is the right balance for reference-carrying variants.


5-10: No leftover uses of PrimitiveObjectValue or .primitive found — transition looks clean.

I searched the repo for the exact symbols/patterns from the original comment and found no matches. The only remaining occurrences of "primitive" are in tests and documentation/comments:

  • Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift — fixture names, test descriptions and comments referencing "primitive" (test data/fixtures).
  • Sources/AblyLiveObjects/Public/PublicTypes.swift — public doc comments describing "primitive" value types.
  • Sources/AblyLiveObjects/Utility/WireCodable.swift — comment: "Extracting primitive values from a dictionary".
  • Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift — comment about handling primitive values per spec.

These are doc/tests-only references and do not reference the removed type/case; no code changes required.

Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsIntegrationTests.swift (9)

141-146: Nice use of literal conformances in fixtures

Using "stringValue" and "" directly as LiveMapValue keeps the fixture terse and validates the new ExpressibleBy*Literal conformances.


425-426: LGTM: createMap entries with literals

Entries ["shouldStay": "foo", "shouldDelete": "bar"] cleanly exercise the literal path and subsequent operations.


452-455: LGTM: map.set with literal value

Using "baz" directly validates the set-path bridging to ObjectData(string:).


2558-2570: Switch cases updated to direct variants

Matching on .data, .string, .number, .bool is consistent with the new public API; the default guard is a reasonable safety net in test code.


2950-2966: Primitive verification for created maps is correct

Post-create assertions for .data/.string/.number/.bool against map contents align with the payload shape emitted by PublicDefaultRealtimeObjects.createMap.


3036-3036: LGTM: createMap entries mixing literal and object reference

This confirms interop between literal values and .liveCounter references in the same operation.


3061-3061: LGTM: client-side initial value for map via literal

This ensures initial map contents are installed locally when publish is suppressed.


3106-3106: LGTM: forge-and-echo flow uses literal entries

Keeps the test succinct while exercising server-applied initialization semantics.


3130-3131: LGTM: local-create test uses literal entry

Confirms local initialization isn’t overridden by a subsequent CREATE op with lower applicability.

@lawrence-forooghian lawrence-forooghian force-pushed the ECO-5465-port-integration-tests branch from c39d55f to 792683d Compare August 15, 2025 16:31
I copied this type blindly from JS in ce8c022, but in JS it doesn't
introduce an annoying extra layer of indirection at the point of usage
like it does here. Get rid of it.
The conversion to use literal syntax was done by Cursor; I've vaguely
satisfied myself that it's caught most of the usages but there may be
some it's missed.

Resolves #65.
@lawrence-forooghian lawrence-forooghian force-pushed the 65-LiveMapValue-improvements branch from 46de61a to 714988d Compare August 15, 2025 16:32
Base automatically changed from ECO-5465-port-integration-tests to main August 20, 2025 20:18
@lawrence-forooghian lawrence-forooghian merged commit 19ba2e9 into main Aug 21, 2025
92 of 98 checks passed
@lawrence-forooghian lawrence-forooghian deleted the 65-LiveMapValue-improvements branch August 21, 2025 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Remove PrimitiveObjectValue, add literal support to LiveMapValue

3 participants