Skip to content
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

Add LiveObjects package test #1921

Merged
merged 2 commits into from
Nov 29, 2024
Merged

Conversation

VeskeR
Copy link
Contributor

@VeskeR VeskeR commented Nov 19, 2024

Test that LiveObjects plugin can be imported and provided to the Ably client, and that TypeScript types for LiveObjects work as expected.
Also update ably.d.ts to include latest public API for LiveObjects (no documentation yet, this is solely to support the tests).

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new HTML file for testing the LiveObjects plugin.
    • Added a new testing function for LiveObjects in the Ably library.
    • Updated bundling process to include additional files for the LiveObjects functionality.
  • Bug Fixes

    • Enhanced error handling in the sandbox API key creation function.
  • Documentation

    • Updated README to clarify LiveObjects plugin usage and bundling changes.
    • Improved TypeScript configuration settings for module resolution.
  • Tests

    • Added new test scenario for LiveObjects plugin export.

@VeskeR VeskeR requested a review from mschristensen November 19, 2024 09:24
Copy link

coderabbitai bot commented Nov 19, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request introduces several updates to the documentation and functionality of the ably-js NPM package, particularly focusing on the LiveObjects plugin. Key changes include the addition of a new HTML file for testing, updates to the README and package.json files to reflect new bundling processes, and the introduction of a new testing function in TypeScript. The modifications enhance the testing framework and clarify the integration of LiveObjects within the package.

Changes

File Path Change Summary
test/package/browser/template/README.md Updated documentation to include import statement for LiveObjects plugin and modified package scripts for bundling.
test/package/browser/template/package.json Updated build script to include bundling for src/index-liveobjects.ts, resulting in three bundles.
test/package/browser/template/server/resources/index-liveobjects.html Added new HTML file for LiveObjects testing, includes script references.
test/package/browser/template/server/server.ts Modified startWebServer to serve index-liveobjects.js alongside existing files.
test/package/browser/template/src/index-liveobjects.ts Introduced new testing function for LiveObjects, verifying TypeScript types and functionality.
test/package/browser/template/test/lib/package.test.ts Added new test scenario for LiveObjects plugin export.
test/package/browser/template/src/sandbox.ts Updated createSandboxAblyAPIKey function to accept optional parameters for customization.
test/package/browser/template/src/tsconfig.json Modified tsconfig.json for improved readability and changed moduleResolution from bundler to node.

Possibly related PRs

Suggested reviewers

  • mschristensen
  • owenpearson

🐰 In the garden, we hop and play,
With LiveObjects brightening our day.
Bundles and tests, all in a row,
Enhancing our package, watch it grow!
With scripts and functions, oh what a sight,
Hopping along, everything feels right! 🌼

Warning

Rate limit exceeded

@VeskeR has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 7 minutes and 32 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 028eec3 and d59e167.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

  • 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.

@github-actions github-actions bot temporarily deployed to staging/pull/1921/bundle-report November 19, 2024 09:25 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/features November 19, 2024 09:25 Inactive
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: 6

🧹 Outside diff range and nitpick comments (6)
ably.d.ts (2)

2035-2035: Reminder: Complete the documentation for the LiveObjects public API

There's a TODO comment indicating that the public API for LiveObjects needs documentation. Please ensure that the documentation is completed before merging.

Would you like assistance in generating the documentation?


2038-2038: Clarify the return type of 'get' method in 'LiveMap'

The get method returns LiveObject | StateValue | undefined, which may be ambiguous. Consider specifying more precise return types or overloading the method to improve type safety and developer experience.

test/package/browser/template/package.json (1)

Line range hint 10-13: Consider adding a dedicated test script for LiveObjects.

Since we're adding LiveObjects functionality, it would be beneficial to have a dedicated test script for LiveObjects tests, similar to how we have separate scripts for lib and hooks tests.

Consider adding this to the "scripts" section:

   "test": "npm run test:lib && npm run test:hooks",
   "test:lib": "playwright test -c playwright-lib.config.js",
   "test:hooks": "playwright test -c playwright-hooks.config.ts",
+  "test:liveobjects": "playwright test -c playwright-liveobjects.config.ts",
   "test:install-deps": "playwright install chromium"
test/package/browser/template/src/index-liveobjects.ts (2)

1-8: LGTM, but consider adding error handling

The setup looks good with proper imports and initialization. However, consider adding error handling for the sandbox API key creation.

 globalThis.testAblyPackage = async function () {
-  const key = await createSandboxAblyAPIKey();
+  try {
+    const key = await createSandboxAblyAPIKey();
+  } catch (error) {
+    console.error('Failed to create sandbox API key:', error);
+    throw error;
+  }

5-41: Consider splitting tests into smaller, focused test cases

The current implementation combines all tests into a single function. Consider splitting it into smaller, focused test cases for better maintainability and clearer failure isolation:

  • Channel initialization
  • LiveMap operations
  • LiveMap subscriptions
  • LiveCounter operations

This would make the tests more maintainable and easier to debug.

Would you like me to provide an example of how to structure these separate test cases?

🧰 Tools
🪛 Biome

[error] 27-27: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

test/package/browser/template/README.md (1)

29-30: Minor formatting suggestion for consistency.

The build script documentation accurately describes the new bundles. Consider using semicolons instead of periods for items 2 and 3 to match the formatting of item 1:

-  2. a bundle containing `src/index-liveobjects.ts` and ably-js.
-  3. a bundle containing `src/index-modular.ts` and ably-js.
+  2. a bundle containing `src/index-liveobjects.ts` and ably-js;
+  3. a bundle containing `src/index-modular.ts` and ably-js.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 928dea7 and 0e63675.

📒 Files selected for processing (7)
  • ably.d.ts (1 hunks)
  • test/package/browser/template/README.md (2 hunks)
  • test/package/browser/template/package.json (1 hunks)
  • test/package/browser/template/server/resources/index-liveobjects.html (1 hunks)
  • test/package/browser/template/server/server.ts (1 hunks)
  • test/package/browser/template/src/index-liveobjects.ts (1 hunks)
  • test/package/browser/template/test/lib/package.test.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • test/package/browser/template/server/resources/index-liveobjects.html
🧰 Additional context used
🪛 LanguageTool
test/package/browser/template/README.md

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

🪛 Biome
test/package/browser/template/src/index-liveobjects.ts

[error] 27-27: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (3)
test/package/browser/template/server/server.ts (1)

8-8: LGTM! Verify the required files exist.

The addition of 'index-liveobjects.js' to the static files array follows the established pattern and supports the LiveObjects testing objective.

Let's verify the required files exist:

test/package/browser/template/package.json (1)

7-7: LGTM! Verify the build output.

The build script modification correctly includes the LiveObjects bundle while maintaining the existing bundling structure.

Let's verify the build output and bundle configuration:

✅ Verification successful

Let me gather more information about the source files to verify their existence and structure.


Let me check for the source files that are referenced in the build script.


Build script configuration is correct and source files are present

All three source files referenced in the build script exist in the correct location:

  • test/package/browser/template/src/index-default.ts
  • test/package/browser/template/src/index-liveobjects.ts
  • test/package/browser/template/src/index-modular.ts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the build output structure and bundle configuration

# Check if the source files exist
echo "Checking source files..."
fd -t f "index-(default|modular|liveobjects)\.ts$" src/

# Verify esbuild can resolve all imports
echo "Verifying esbuild can resolve imports..."
for file in src/index-{default,liveobjects,modular}.ts; do
  if [ -f "$file" ]; then
    esbuild --bundle "$file" --outdir=dist --analyze
  fi
done

Length of output: 484


Script:

#!/bin/bash
# Let's check the entire src directory structure and content
echo "Checking src directory structure:"
fd . src/

echo -e "\nChecking package.json location and content:"
fd package.json
cat test/package/browser/template/package.json

Length of output: 8303


Script:

#!/bin/bash
# Check for the existence of the specific index files in the test package
echo "Checking for index files in test/package/browser/template/src:"
ls -la test/package/browser/template/src/index-*.ts 2>/dev/null || echo "No index files found"

# Check if there are any index files anywhere in the repository
echo -e "\nSearching for index files repository-wide:"
fd "index-(default|modular|liveobjects)\.ts$"

Length of output: 910

test/package/browser/template/README.md (1)

11-11: LGTM! Clear documentation of LiveObjects plugin import.

The import statement documentation is well-structured and consistent with other import examples in the file.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

ably.d.ts Outdated Show resolved Hide resolved
ably.d.ts Outdated Show resolved Hide resolved
test/package/browser/template/src/index-liveobjects.ts Outdated Show resolved Hide resolved
@VeskeR VeskeR force-pushed the liveobjects/package-test branch from 0e63675 to b7eeff6 Compare November 19, 2024 09:45
@github-actions github-actions bot temporarily deployed to staging/pull/1921/features November 19, 2024 09:46 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/bundle-report November 19, 2024 09:46 Inactive
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: 2

🧹 Outside diff range and nitpick comments (3)
test/package/browser/template/src/index-liveobjects.ts (1)

5-41: Consider splitting tests by functionality

The current test function combines multiple concerns (LiveMap and LiveCounter testing) and mixes type checking with functional testing. Consider splitting it into separate test functions for better maintainability:

  1. testLiveMapTypes - For LiveMap type checking
  2. testLiveMapFunctionality - For LiveMap runtime behavior
  3. testLiveCounterTypes - For LiveCounter type checking
  4. testLiveCounterFunctionality - For LiveCounter runtime behavior

This separation would make the tests more focused and easier to maintain.

🧰 Tools
🪛 Biome

[error] 27-27: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

test/package/browser/template/README.md (2)

29-30: Fix list numbering and enhance bundle documentation.

The current documentation has inconsistent numbering and could benefit from additional context:

  1. Fix the numbering sequence
  2. Add a brief explanation of the LiveObjects bundle's purpose

Consider this improvement:

  1. a bundle containing `src/index-default.ts` and ably-js;
- 2. a bundle containing `src/index-liveobjects.ts` and ably-js.
- 3. a bundle containing `src/index-modular.ts` and ably-js.
+ 2. a bundle containing `src/index-liveobjects.ts` and ably-js for testing LiveObjects plugin functionality;
+ 3. a bundle containing `src/index-modular.ts` and ably-js for testing tree-shakable imports.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


Line range hint 1-30: Consider adding TypeScript types testing documentation.

The PR objectives mention validating TypeScript types for LiveObjects, but this isn't explicitly covered in the documentation. Consider adding a note about TypeScript types testing under the "typecheck" script section.

Add something like:

- `typecheck`: Type-checks the code that imports ably-js.
+ `typecheck`: Type-checks the code that imports ably-js, including validation of LiveObjects TypeScript types.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~8-~8: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...tains three files, each of which import ably-js in different manners, and provide a way...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~10-~10: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...c/index-default.ts imports the default ably-js package (import { Realtime } from 'abl...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[style] ~12-~12: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...iveobjects'). - src/index-modular.ts imports the tree-shakable ably-js package (imp...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[uncategorized] ~12-~12: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...x-modular.ts imports the tree-shakable ably-js package (import { BaseRealtime, WebSoc...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[style] ~13-~13: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... 'ably/modular'). - src/ReactApp.tsx imports React hooks from the ably-js package (...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[uncategorized] ~13-~13: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ctApp.tsx imports React hooks from the ably-js package (import { useChannel } from 'a...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0e63675 and b7eeff6.

📒 Files selected for processing (6)
  • test/package/browser/template/README.md (2 hunks)
  • test/package/browser/template/package.json (1 hunks)
  • test/package/browser/template/server/resources/index-liveobjects.html (1 hunks)
  • test/package/browser/template/server/server.ts (1 hunks)
  • test/package/browser/template/src/index-liveobjects.ts (1 hunks)
  • test/package/browser/template/test/lib/package.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • test/package/browser/template/package.json
  • test/package/browser/template/server/resources/index-liveobjects.html
  • test/package/browser/template/server/server.ts
  • test/package/browser/template/test/lib/package.test.ts
🧰 Additional context used
🪛 LanguageTool
test/package/browser/template/README.md

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

🪛 Biome
test/package/browser/template/src/index-liveobjects.ts

[error] 27-27: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (4)
test/package/browser/template/src/index-liveobjects.ts (3)

10-13: Add connection state handling

The previous review comment about adding connection state handling is still valid.


19-31: Fix switch statement scoping

The previous review comment about fixing switch statement scoping and adding error handling is still valid.

🧰 Tools
🪛 Biome

[error] 27-27: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


32-41: Test with actual LiveCounter instance

The previous review comment about testing with an actual LiveCounter instance is still valid.

test/package/browser/template/README.md (1)

11-11: LGTM! Clear and consistent documentation.

The LiveObjects plugin import documentation follows the established pattern and accurately reflects the intended usage.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

@VeskeR VeskeR force-pushed the liveobjects/package-test branch from b7eeff6 to f03ca11 Compare November 19, 2024 09:52
@github-actions github-actions bot temporarily deployed to staging/pull/1921/bundle-report November 19, 2024 09:53 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/features November 19, 2024 09:53 Inactive
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: 2

🧹 Outside diff range and nitpick comments (3)
test/package/browser/template/src/sandbox.ts (1)

3-3: Consider adding JSDoc documentation for the withOptions parameter.

Since this is a test utility that others might use, it would be helpful to document the expected shape and purpose of the withOptions parameter.

+/**
+ * Creates a sandbox API key for testing purposes
+ * @param withOptions - Optional configuration to merge with the default test app setup
+ * @returns Promise<string> The API key string
+ */
 export async function createSandboxAblyAPIKey(withOptions?: object) {
test/package/browser/template/src/index-liveobjects.ts (1)

33-33: Improve type safety of LiveCounter retrieval

The type assertion to LiveCounter could be unsafe. Consider using type guards or runtime type checking.

-  const counter = root.get('randomKey') as Ably.LiveCounter | undefined;
+  const value = root.get('randomKey');
+  const counter = value && 'value' in value && 'increment' in value
+    ? value as Ably.LiveCounter
+    : undefined;
test/package/browser/template/README.md (1)

29-30: Enhance build script documentation clarity.

While the additions correctly document the new bundles, consider these improvements for better clarity:

  1. Use consistent numbering format (all entries should end with ".")
  2. Add brief explanations of each bundle's purpose, especially for the LiveObjects and modular bundles.

Here's a suggested improvement:

  1. a bundle containing `src/index-default.ts` and ably-js;
- 2. a bundle containing `src/index-liveobjects.ts` and ably-js.
- 3. a bundle containing `src/index-modular.ts` and ably-js.
+ 2. a bundle containing `src/index-liveobjects.ts` and ably-js for testing LiveObjects plugin functionality;
+ 3. a bundle containing `src/index-modular.ts` and ably-js for testing tree-shakable imports;
🧰 Tools
🪛 LanguageTool

[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between b7eeff6 and f03ca11.

📒 Files selected for processing (7)
  • test/package/browser/template/README.md (2 hunks)
  • test/package/browser/template/package.json (1 hunks)
  • test/package/browser/template/server/resources/index-liveobjects.html (1 hunks)
  • test/package/browser/template/server/server.ts (1 hunks)
  • test/package/browser/template/src/index-liveobjects.ts (1 hunks)
  • test/package/browser/template/src/sandbox.ts (1 hunks)
  • test/package/browser/template/test/lib/package.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • test/package/browser/template/package.json
  • test/package/browser/template/server/resources/index-liveobjects.html
  • test/package/browser/template/server/server.ts
  • test/package/browser/template/test/lib/package.test.ts
🧰 Additional context used
🪛 LanguageTool
test/package/browser/template/README.md

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

🪛 Biome
test/package/browser/template/src/index-liveobjects.ts

[error] 27-27: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (2)
test/package/browser/template/src/sandbox.ts (1)

3-7: LGTM! Clean implementation of optional configuration.

The implementation correctly uses the spread operator with nullish coalescing to merge optional configurations while maintaining backward compatibility.

test/package/browser/template/README.md (1)

11-11: LGTM! Clear documentation of LiveObjects import.

The added documentation clearly shows how to import the LiveObjects plugin, which aligns well with the PR's objective of implementing LiveObjects plugin testing.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

test/package/browser/template/src/index-liveobjects.ts Outdated Show resolved Hide resolved
@VeskeR VeskeR force-pushed the liveobjects/package-test branch from f03ca11 to 1fe3fd3 Compare November 22, 2024 08:58
@VeskeR VeskeR changed the base branch from integration/liveobjects to liveobjects/isolated-create-ops-and-vector-timeserials November 22, 2024 08:58
@github-actions github-actions bot temporarily deployed to staging/pull/1921/bundle-report November 22, 2024 08:59 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/features November 22, 2024 08:59 Inactive
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.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

Actionable comments posted: 14

🧹 Outside diff range and nitpick comments (29)
test/package/browser/template/README.md (2)

29-30: Consider enhancing bundle documentation.

While the bundle additions are documented, it would be helpful to briefly explain the purpose of each bundle, particularly why LiveObjects requires a separate bundle. This would help developers understand the testing strategy better.

Consider adding brief explanations like:

  2. a bundle containing `src/index-liveobjects.ts` and ably-js.
+     // Tests LiveObjects plugin integration and type definitions
  3. a bundle containing `src/index-modular.ts` and ably-js.
+     // Tests tree-shakable package functionality
🧰 Tools
🪛 LanguageTool

[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


Documentation needs to be enhanced with test implementation details

The README should be updated to include:

  • sandbox.ts: A utility file that provides sandbox API key creation for testing
  • test/hooks/ReactApp.spec.tsx: The Playwright component test implementation for React hooks
  • test/lib/package.test.ts: The main test suite that verifies different package export scenarios

These files are integral to the testing setup and their documentation would provide valuable context for developers working with the test suite.

🔗 Analysis chain

Line range hint 1-30: Verify test documentation completeness.

Let's ensure all test-related files are properly documented in the README.


Documentation missing for test files and test implementation details

The following test-related files are not documented in the README:

  • sandbox.ts: A source file that might be used for testing
  • ReactApp.spec.tsx: The React hooks test implementation file
  • package.test.ts: The main package test implementation file

Let's verify the purpose of these files to ensure they warrant documentation:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any test files that might need documentation

# Find all test-related files
echo "=== Test files that might need documentation ==="
fd -e ts -e tsx . test/package/browser/template/src test/package/browser/template/test \
  | grep -i "liveobjects\|test" \
  | while read -r file; do
    if ! grep -q "$(basename "$file")" test/package/browser/template/README.md; then
      echo "Missing documentation for: $file"
    fi
done

Length of output: 1762


Script:

#!/bin/bash
# Check contents of undocumented files
echo "=== sandbox.ts contents ==="
head -n 20 test/package/browser/template/src/sandbox.ts

echo -e "\n=== ReactApp.spec.tsx contents ==="
head -n 20 test/package/browser/template/test/hooks/ReactApp.spec.tsx

echo -e "\n=== package.test.ts contents ==="
head -n 20 test/package/browser/template/test/lib/package.test.ts

Length of output: 2525

🧰 Tools
🪛 LanguageTool

[uncategorized] ~8-~8: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...tains three files, each of which import ably-js in different manners, and provide a way...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~10-~10: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...c/index-default.ts imports the default ably-js package (import { Realtime } from 'abl...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[style] ~12-~12: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...iveobjects'). - src/index-modular.ts imports the tree-shakable ably-js package (imp...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[uncategorized] ~12-~12: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...x-modular.ts imports the tree-shakable ably-js package (import { BaseRealtime, WebSoc...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[style] ~13-~13: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... 'ably/modular'). - src/ReactApp.tsx imports React hooks from the ably-js package (...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[uncategorized] ~13-~13: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ctApp.tsx imports React hooks from the ably-js package (import { useChannel } from 'a...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

src/plugins/liveobjects/syncliveobjectsdatapool.ts (2)

4-7: Architectural change: Simplified state management through StateObject

The shift from LiveObjectData to StateObject represents a cleaner approach to state management. This change reduces complexity by eliminating the intermediate objectData layer.

Consider documenting this architectural decision in the codebase to explain the rationale behind using StateObject directly.


82-96: Consider further simplification of data entry creation

The _createLiveCounterDataEntry and _createLiveMapDataEntry methods now simply wrap stateObject with type information. This could be further simplified.

Consider this more concise approach:

-  private _createLiveCounterDataEntry(stateObject: StateObject): LiveCounterDataEntry {
-    const newEntry: LiveCounterDataEntry = {
-      stateObject,
-      objectType: 'LiveCounter',
-    };
-    return newEntry;
-  }
+  private _createLiveCounterDataEntry(stateObject: StateObject): LiveCounterDataEntry {
+    return { stateObject, objectType: 'LiveCounter' };
+  }

-  private _createLiveMapDataEntry(stateObject: StateObject): LiveMapDataEntry {
-    const newEntry: LiveMapDataEntry = {
-      stateObject,
-      objectType: 'LiveMap',
-    };
-    return newEntry;
-  }
+  private _createLiveMapDataEntry(stateObject: StateObject): LiveMapDataEntry {
+    return { stateObject, objectType: 'LiveMap' };
+  }
src/plugins/liveobjects/timeserial.ts (2)

12-16: Enhance documentation for the siteCode property

While the property is properly documented, consider enhancing the JSDoc comment to explain what a site code represents and its significance in the context of timeserials.


Line range hint 1-180: Consider test implications of temporary implementation

Since this is part of adding LiveObjects package test and the siteCode implementation is temporary, ensure that:

  1. Tests are aware of the temporary nature of the implementation
  2. Tests are designed to be adaptable when the implementation changes
  3. Consider adding a comment in the test files noting the dependency on this temporary implementation

This will help prevent test brittleness when the final implementation is added.

src/plugins/liveobjects/liveobjects.ts (2)

89-99: Consider adding error handling for invalid state messages

The state message handling logic is correct, but consider adding validation for the incoming state messages to ensure robustness.

Consider adding validation:

 handleStateMessages(stateMessages: StateMessage[]): void {
+  if (!Array.isArray(stateMessages)) {
+    this._client.Logger.logAction(
+      this._client.logger,
+      this._client.Logger.LOG_ERROR,
+      'LiveObjects.handleStateMessages()',
+      'Invalid state messages received',
+    );
+    return;
+  }
   if (this._syncInProgress) {
     this._bufferedStateOperations.push(...stateMessages);
     return;
   }
   this._liveObjectsPool.applyStateMessages(stateMessages);
 }

Line range hint 198-214: Consider adding type validation before state override

While the implementation is correct, consider adding type validation before overriding state objects to ensure type safety.

Consider adding validation:

 if (existingObject) {
+  if (entry.objectType !== existingObject.type) {
+    throw new this._client.ErrorInfo(
+      `Type mismatch: existing=${existingObject.type}, new=${entry.objectType}`,
+      50000,
+      500
+    );
+  }
   const update = existingObject.overrideWithStateObject(entry.stateObject);
   existingObjectUpdates.push({ object: existingObject, update });
   continue;
 }
test/common/modules/live_objects_helper.js (1)

104-106: Document the purpose of map semantics field.

The newly added semantics field is hardcoded to 0 without any explanation of its purpose or possible values. Consider adding a comment or documentation explaining what this field represents and what other values it might support.

src/common/lib/client/realtimechannel.ts (1)

652-652: Consider consistency between STATE and STATE_SYNC message handling

There's an inconsistency in how channelSerial is handled between STATE and STATE_SYNC messages:

  • handleStateMessages (STATE): called without channelSerial
  • handleStateSyncMessages (STATE_SYNC): called with channelSerial

This difference in behavior should be documented or aligned if not intentional.

Also applies to: 687-687

ably.d.ts (8)

2031-2034: Add JSDoc documentation for LiveObjects interface

The LiveObjects interface is missing JSDoc documentation to describe its purpose and usage. Consider adding comprehensive documentation similar to other interfaces in this file.

+/**
+ * Enables real-time synchronization of data structures between clients.
+ * Provides access to live data types like maps and counters that automatically
+ * sync changes across connected clients.
+ */
 export declare interface LiveObjects {
   getRoot(): Promise<LiveMap>;
 }

2037-2040: Add JSDoc documentation for LiveMap interface and methods

The LiveMap interface and its methods lack documentation. Add JSDoc to explain the purpose of the interface and the behavior of each method.

+/**
+ * Represents a synchronized map data structure that can contain both primitive values
+ * and nested LiveObjects. Changes to the map are automatically synchronized across
+ * connected clients.
+ */
 export declare interface LiveMap extends LiveObject<LiveMapUpdate> {
+  /**
+   * Retrieves the value associated with the specified key.
+   * @param key - The key to look up in the map
+   * @returns The value if found (either a LiveObject or primitive), undefined if not found
+   */
   get(key: string): LiveObject | StateValue | undefined;
+  /**
+   * Returns the number of key-value pairs in the map.
+   * @returns The size of the map
+   */
   size(): number;
 }

2042-2044: Add JSDoc documentation for LiveMapUpdate interface

The LiveMapUpdate interface needs documentation to explain its role in tracking map changes.

+/**
+ * Represents an update event for a LiveMap, containing information about
+ * which keys were updated or removed in the map.
+ */
 export declare interface LiveMapUpdate extends LiveObjectUpdate {
+  /**
+   * A record of changes where each key maps to either 'updated' or 'removed'
+   * to indicate the type of change that occurred.
+   */
   update: { [keyName: string]: 'updated' | 'removed' };
 }

2048-2050: Add JSDoc documentation for LiveCounter interface

The LiveCounter interface needs documentation to explain its purpose and behavior.

+/**
+ * Represents a synchronized counter that can be incremented or decremented
+ * across connected clients. All changes are automatically synchronized.
+ */
 export declare interface LiveCounter extends LiveObject<LiveCounterUpdate> {
+  /**
+   * Returns the current value of the counter.
+   * @returns The current numeric value of the counter
+   */
   value(): number;
 }

2052-2054: Add JSDoc documentation for LiveCounterUpdate interface

The LiveCounterUpdate interface needs documentation to explain its role in counter updates.

+/**
+ * Represents an update event for a LiveCounter, containing the
+ * increment/decrement value that was applied.
+ */
 export declare interface LiveCounterUpdate extends LiveObjectUpdate {
+  /**
+   * The value by which the counter was incremented (positive)
+   * or decremented (negative).
+   */
   update: { inc: number };
 }

2056-2060: Add JSDoc documentation for LiveObject interface

The base LiveObject interface needs documentation to explain its role as the foundation for live data types.

+/**
+ * Base interface for all live data types that can be synchronized across clients.
+ * Provides subscription capabilities for tracking changes to the object.
+ */
 export declare interface LiveObject<TUpdate extends LiveObjectUpdate = LiveObjectUpdate> {
+  /**
+   * Subscribes to updates on this live object.
+   * @param listener - Callback function that will be invoked with update events
+   * @returns A subscription response object that can be used to unsubscribe
+   */
   subscribe(listener: (update: TUpdate) => void): SubscribeResponse;
+  /**
+   * Removes a specific update listener.
+   * @param listener - The callback function to remove
+   */
   unsubscribe(listener: (update: TUpdate) => void): void;
+  /**
+   * Removes all update listeners from this object.
+   */
   unsubscribeAll(): void;
 }

2066-2068: Add JSDoc documentation for SubscribeResponse interface

The SubscribeResponse interface needs documentation to explain its purpose in subscription management.

+/**
+ * Represents a subscription handle returned when subscribing to live object updates.
+ * Can be used to unsubscribe from further updates.
+ */
 export declare interface SubscribeResponse {
+  /**
+   * Cancels the subscription and stops receiving updates.
+   */
   unsubscribe(): void;
 }

2031-2068: Consider adding error handling and connection state management

The LiveObjects implementation could benefit from additional considerations:

  1. Error Handling: Consider adding error cases in the type definitions, such as handling synchronization conflicts or network issues.
  2. Connection State: Consider exposing synchronization state to allow applications to show appropriate loading/error states.
  3. Batch Operations: Consider adding support for batch operations on LiveMap to optimize network usage.
src/plugins/liveobjects/liveobjectspool.ts (1)

92-92: Typo in comment: 'ba able' should be 'be able'

Correct the typographical error to improve code documentation clarity.

Apply this diff to fix the typo:

- // since they need to ba able to eventually initialize themselves from that *_CREATE op.
+ // since they need to be able to eventually initialize themselves from that *_CREATE op.
src/plugins/liveobjects/liveobject.ts (3)

114-125: Refactor _timeserialMapFromStringMap for Improved Readability

The current implementation using reduce may be less readable. Consider refactoring the method for better clarity.

Suggested refactor:

protected _timeserialMapFromStringMap(stringTimeserialsMap: Record<string, string>): Record<string, Timeserial> {
  const objTimeserialsMap: Record<string, Timeserial> = {};
  for (const [key, timeserialString] of Object.entries(stringTimeserialsMap)) {
    objTimeserialsMap[key] = DefaultTimeserial.calculateTimeserial(this._client, timeserialString);
  }
  return objTimeserialsMap;
}

137-137: Document Parameters in applyOperation Method

Ensure that the abstract applyOperation method has clear documentation detailing the purpose of the op and msg parameters to guide subclass implementations.


155-156: Clarify Purpose of _updateFromDataDiff Method

Ensure that the _updateFromDataDiff method accurately computes the update object based on the differences between prevDataRef and newDataRef. Clear documentation will aid in maintaining and extending this functionality.

src/plugins/liveobjects/statemessage.ts (1)

283-300: Simplify buffer handling in _encodeStateValue method

The buffer handling logic can be clarified for better readability and efficiency. Consider refactoring the method to make the conditions and returns more straightforward.

For example:

private static _encodeStateValue(
  platform: typeof Platform,
  value: StateValue | undefined,
  encoding: string | undefined,
  withBase64Encoding: boolean,
): {
  value: StateValue | undefined;
  encoding: string | undefined;
} {
  if (!value || !platform.BufferUtils.isBuffer(value)) {
    return { value, encoding };
  }

  if (withBase64Encoding) {
    return {
      value: platform.BufferUtils.base64Encode(value),
      encoding: encoding ? encoding + '/base64' : 'base64',
    };
  }

  return {
    value: platform.BufferUtils.toBuffer(value),
    encoding,
  };
}
src/plugins/liveobjects/livemap.ts (3)

183-240: Ensure 'overrideWithStateObject' method handles all validation cases

The overrideWithStateObject method performs multiple validations on the stateObject. Confirm that all possible invalid states are covered and that error messages are informative for easier debugging.

Consider adding additional validation or refining error messages for clarity.


Line range hint 246-284: Optimize the data difference calculation in '_updateFromDataDiff'

The _updateFromDataDiff method compares previous and new data to determine updates. For performance enhancement, consider optimizing the loops or using more efficient data comparison strategies, especially for large datasets.

For example, you might:

  • Break early from loops when possible.
  • Use more efficient data structures for lookup.

338-344: Clarify error handling in '_throwNoPayloadError'

The _throwNoPayloadError method throws an ErrorInfo when no payload is found. Ensure that the error message includes sufficient context for debugging.

Consider including the operation details in the error message:

- `No payload found for ${op.action} op for LiveMap objectId=${this.getObjectId()}`
+ `No payload found for ${op.action} operation on LiveMap with objectId=${this.getObjectId()}`
test/realtime/live_objects.test.js (3)

623-623: Typographical Correction in Test Description

Consider rephrasing the test description for clarity. Suggest changing:

  • From: 'MAP_CREATE state operation messages are applied based on the site timeserials vector of the object'
  • To: 'MAP_CREATE state operation messages are applied based on the object's site timeserials vector'

1449-1451: Potential Numeric Overflow with Math.pow(10, i + 1)

In the loop incrementing the counter:

amount: Math.pow(10, i + 1)
  • Be cautious with large exponentiation as it may lead to values exceeding the maximum safe integer limit in JavaScript (Number.MAX_SAFE_INTEGER).
  • Consider using safe arithmetic operations or adding checks to prevent potential overflow.

1214-1220: Ensure Unique Test Channel Names

When generating test channel names based on the scenario description:

const channelName = scenario.description;
  • Using the entire description as the channel name may result in long or duplicate names.
  • Consider sanitizing and shortening the channel name to ensure it is unique and conforms to channel naming conventions.
🛑 Comments failed to post (14)
test/package/browser/template/src/index-liveobjects.ts (4)

8-8: 🛠️ Refactor suggestion

Add connection state verification

Verify that the Realtime instance is properly connected before proceeding with tests.

   const realtime = new Ably.Realtime({ key, environment: 'sandbox', plugins: { LiveObjects } });
+  await new Promise<void>((resolve, reject) => {
+    realtime.connection.once('connected', () => resolve());
+    realtime.connection.once('failed', (err) => reject(err));
+  });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  const realtime = new Ably.Realtime({ key, environment: 'sandbox', plugins: { LiveObjects } });
  await new Promise<void>((resolve, reject) => {
    realtime.connection.once('connected', () => resolve());
    realtime.connection.once('failed', (err) => reject(err));
  });

21-28: ⚠️ Potential issue

Fix switch statement declaration scope

The shouldExhaustAllTypes declaration can be erroneously accessed from other cases.

     switch (update.someKey) {
       case 'removed':
       case 'updated':
         break;
       default: {
         // check all possible types are exhausted
         const shouldExhaustAllTypes: never = update.someKey;
+        break;
+      }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    switch (update.someKey) {
      case 'removed':
      case 'updated':
        break;
      default: {
        // check all possible types are exhausted
        const shouldExhaustAllTypes: never = update.someKey;
        break;
      }
    }
🧰 Tools
🪛 Biome (1.9.4)

[error] 27-27: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


5-41: 🛠️ Refactor suggestion

Improve overall test structure and error handling

The test should follow a proper structure with setup, execution, and cleanup phases.

-globalThis.testAblyPackage = async function () {
+globalThis.testAblyPackage = async function () {
+  let realtime: Ably.Realtime | undefined;
+  let cleanup: (() => Promise<void>)[] = [];
+
+  try {
     const key = await createSandboxAblyAPIKey({ featureFlags: ['enableChannelState'] });
     const realtime = new Ably.Realtime({ key, environment: 'sandbox', plugins: { LiveObjects } });
+    cleanup.push(() => realtime.close());

     // ... rest of the test code ...

+  } catch (error) {
+    console.error('Test failed:', error);
+    throw error;
+  } finally {
+    // Execute cleanup in reverse order
+    for (const cleanupFn of cleanup.reverse()) {
+      try {
+        await cleanupFn();
+      } catch (error) {
+        console.error('Cleanup failed:', error);
+      }
+    }
+  }
 };

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (1.9.4)

[error] 27-27: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


32-41: 🛠️ Refactor suggestion

Add test coverage for LiveCounter operations

The current test only verifies TypeScript types. Add test coverage for actual LiveCounter operations:

  • Increment/decrement operations
  • Value updates
  • Concurrent modifications
-  // check LiveCounter types also behave as expected
-  const counter = root.get('randomKey') as Ably.LiveCounter | undefined;
-  // use nullish coalescing as we didn't actually create a counter object on the root,
-  // so the next calls would fail. we only need to check that TypeScript types work
-  counter?.value();
-  const counterSubscribeResponse = counter?.subscribe(({ update }) => {
-    const shouldBeANumber: number = update.inc;
-  });
-  counterSubscribeResponse?.unsubscribe();
+  // Test actual LiveCounter operations
+  const counter = await liveObjects.createCounter('testCounter', 0);
+  try {
+    // Test initial value
+    console.assert(counter.value() === 0, 'Initial value should be 0');
+
+    // Test increment
+    await counter.increment(5);
+    console.assert(counter.value() === 5, 'Value should be 5 after increment');
+
+    // Test decrement
+    await counter.decrement(2);
+    console.assert(counter.value() === 3, 'Value should be 3 after decrement');
+
+    // Test subscription
+    const updates: number[] = [];
+    const subscription = counter.subscribe(({ update }) => {
+      updates.push(update.inc);
+    });
+
+    // Test concurrent modifications
+    await Promise.all([
+      counter.increment(1),
+      counter.increment(2),
+      counter.decrement(1)
+    ]);
+
+    subscription.unsubscribe();
+    console.assert(updates.length === 3, 'Should receive 3 updates');
+  } finally {
+    await root.delete('testCounter');
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  // Test actual LiveCounter operations
  const counter = await liveObjects.createCounter('testCounter', 0);
  try {
    // Test initial value
    console.assert(counter.value() === 0, 'Initial value should be 0');

    // Test increment
    await counter.increment(5);
    console.assert(counter.value() === 5, 'Value should be 5 after increment');

    // Test decrement
    await counter.decrement(2);
    console.assert(counter.value() === 3, 'Value should be 3 after decrement');

    // Test subscription
    const updates: number[] = [];
    const subscription = counter.subscribe(({ update }) => {
      updates.push(update.inc);
    });

    // Test concurrent modifications
    await Promise.all([
      counter.increment(1),
      counter.increment(2),
      counter.decrement(1)
    ]);

    subscription.unsubscribe();
    console.assert(updates.length === 3, 'Should receive 3 updates');
  } finally {
    await root.delete('testCounter');
  }
src/plugins/liveobjects/statemessage.ts (6)

154-155: ⚠️ Potential issue

Replace 'this' with class name in static methods for clarity

Using this in static methods can be misleading, as this refers to the class itself. It's clearer and more conventional to use the class name directly. Please replace this with StateMessage in the following static methods.

Apply the following changes:

Line 154:

- await this._decodeMapEntries(message.object.map.entries, inputContext, decodeDataFn);
+ await StateMessage._decodeMapEntries(message.object.map.entries, inputContext, decodeDataFn);

Line 158:

- await this._decodeMapEntries(message.object.createOp.map.entries, inputContext, decodeDataFn);
+ await StateMessage._decodeMapEntries(message.object.createOp.map.entries, inputContext, decodeDataFn);

Line 162:

- await this._decodeStateData(message.object.createOp.mapOp.data, inputContext, decodeDataFn);
+ await StateMessage._decodeStateData(message.object.createOp.mapOp.data, inputContext, decodeDataFn);

Line 166:

- await this._decodeMapEntries(message.operation.map.entries, inputContext, decodeDataFn);
+ await StateMessage._decodeMapEntries(message.operation.map.entries, inputContext, decodeDataFn);

Line 170:

- await this._decodeStateData(message.operation.mapOp.data, inputContext, decodeDataFn);
+ await StateMessage._decodeStateData(message.operation.mapOp.data, inputContext, decodeDataFn);

Also applies to: 158-159, 162-163, 166-167, 170-171

🧰 Tools
🪛 Biome (1.9.4)

[error] 154-154: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


224-225: ⚠️ Potential issue

Replace 'this' with class name in static methods for clarity

In the _encodeStateOperation method, using the class name improves readability. Please update the references accordingly.

Apply the following changes:

Line 224:

- stateOperationCopy.mapOp.data = this._encodeStateData(platform, stateOperation.mapOp?.data!, withBase64Encoding);
+ stateOperationCopy.mapOp.data = StateMessage._encodeStateData(platform, stateOperation.mapOp?.data!, withBase64Encoding);

Line 230:

- entry.data = this._encodeStateData(platform, stateOperation?.map?.entries?.[key].data!, withBase64Encoding);
+ entry.data = StateMessage._encodeStateData(platform, stateOperation?.map?.entries?.[key].data!, withBase64Encoding);

Also applies to: 230-231

🧰 Tools
🪛 Biome (1.9.4)

[error] 224-224: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


320-325: ⚠️ Potential issue

Clarify the use of arguments in toJSON method

Using arguments.length > 0 to detect JSON.stringify() calls can be unreliable and may lead to unexpected behaviors. Consider using a more explicit approach to determine when base64 encoding is needed.

For instance, you could add a parameter to the method to indicate whether base64 encoding should be applied.

toJSON(withBase64Encoding = false): { ... } {
  // Existing logic using the `withBase64Encoding` parameter
}

266-267: ⚠️ Potential issue

Replace 'this' with class name in static methods for clarity

In the _encodeStateData method, replacing this._encodeStateValue with StateMessage._encodeStateValue enhances clarity.

Apply the following change:

Line 266:

- const { value, encoding } = this._encodeStateValue(platform, data?.value, data?.encoding, withBase64Encoding);
+ const { value, encoding } = StateMessage._encodeStateValue(platform, data?.value, data?.encoding, withBase64Encoding);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    const { value, encoding } = StateMessage._encodeStateValue(platform, data?.value, data?.encoding, withBase64Encoding);
    return {
🧰 Tools
🪛 Biome (1.9.4)

[error] 266-266: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


195-196: ⚠️ Potential issue

Replace 'this' with class name in static methods for clarity

In the _decodeMapEntries static method, replace this._decodeStateData with StateMessage._decodeStateData to maintain consistency and avoid confusion.

Apply the following change:

Line 195:

- await this._decodeStateData(entry.data, inputContext, decodeDataFn);
+ await StateMessage._decodeStateData(entry.data, inputContext, decodeDataFn);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

      await StateMessage._decodeStateData(entry.data, inputContext, decodeDataFn);
    }
🧰 Tools
🪛 Biome (1.9.4)

[error] 195-195: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


259-260: ⚠️ Potential issue

Replace 'this' with class name in static methods for clarity

In the _encodeStateObject method, update this._encodeStateOperation to StateMessage._encodeStateOperation.

Apply the following change:

Line 259:

- stateObjectCopy.createOp = this._encodeStateOperation(platform, stateObject.createOp!, withBase64Encoding);
+ stateObjectCopy.createOp = StateMessage._encodeStateOperation(platform, stateObject.createOp!, withBase64Encoding);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

      stateObjectCopy.createOp = StateMessage._encodeStateOperation(platform, stateObject.createOp!, withBase64Encoding);
    }
🧰 Tools
🪛 Biome (1.9.4)

[error] 259-259: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

src/plugins/liveobjects/livemap.ts (3)

456-484: ⚠️ Potential issue

Ensure proper handling of 'entry.data' in '_liveMapDataFromMapEntries'

In the _liveMapDataFromMapEntries method, when creating liveData, the code assumes that either entry.data.objectId or entry.data.value exists. To prevent runtime errors, include validation to handle cases where entry.data might be missing or incomplete.

Add checks to confirm that entry.data is defined and contains the expected properties.


72-75: ⚠️ Potential issue

Handle potential undefined 'semantics' in 'fromStateObject' method

The use of the non-null assertion operator ! on stateObject.map?.semantics! assumes that stateObject.map and stateObject.map.semantics are always defined. If stateObject.map is undefined, this will result in a runtime error. It's safer to include null checks to ensure robustness.

Consider modifying the code to include null checks:

- const obj = new LiveMap(liveobjects, stateObject.map?.semantics!, stateObject.objectId);
+ if (!stateObject.map || !stateObject.map.semantics) {
+   throw new this._client.ErrorInfo(
+     'Invalid state object: missing map semantics',
+     50000,
+     500,
+   );
+ }
+ const obj = new LiveMap(liveobjects, stateObject.map.semantics, stateObject.objectId);

Committable suggestion skipped: line range outside the PR's diff.


346-369: ⚠️ Potential issue

Validate semantics match in '_applyMapCreate' method

In the _applyMapCreate method, you check if this._semantics matches op.map?.semantics. If op.map is undefined, accessing op.map.semantics could cause an error. Add a null check for op.map to prevent this.

Modify the code to include a null check:

- if (this._semantics !== op.map?.semantics) {
+ if (!op.map || this._semantics !== op.map.semantics) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  private _applyMapCreate(op: StateOperation): LiveMapUpdate | LiveObjectUpdateNoop {
    if (this._createOperationIsMerged) {
      // There can't be two different create operation for the same object id, because the object id
      // fully encodes that operation. This means we can safely ignore any new incoming create operations
      // if we already merged it once.
      this._client.Logger.logAction(
        this._client.logger,
        this._client.Logger.LOG_MICRO,
        'LiveMap._applyMapCreate()',
        `skipping applying MAP_CREATE op on a map instance as it was already applied before; objectId=${this._objectId}`,
      );
      return { noop: true };
    }

    if (!op.map || this._semantics !== op.map.semantics) {
      throw new this._client.ErrorInfo(
        `Cannot apply MAP_CREATE op on LiveMap objectId=${this.getObjectId()}; map's semantics=${this._semantics}, but op expected ${op.map?.semantics}`,
        50000,
        500,
      );
    }

    return this._mergeInitialDataFromCreateOperation(op);
  }
test/realtime/live_objects.test.js (1)

827-834: ⚠️ Potential issue

Inconsistent Comment Regarding Site CGOs

In the test cases for COUNTER_CREATE operations:

  • For serial 'bbb@2-0', the comment reads "existing site, later CGO, applied", which is correct.
  • However, for serial 'aaa@0-0', the comment says "different site, earlier CGO, applied". This seems inconsistent since an earlier CGO would typically not be applied.
  • Please review and correct the comments to accurately reflect the logic.

@VeskeR VeskeR force-pushed the liveobjects/isolated-create-ops-and-vector-timeserials branch from e151919 to 567ad15 Compare November 22, 2024 17:09
@VeskeR VeskeR force-pushed the liveobjects/package-test branch from 1fe3fd3 to 9da78a6 Compare November 22, 2024 17:31
@github-actions github-actions bot temporarily deployed to staging/pull/1921/bundle-report November 22, 2024 17:31 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/features November 22, 2024 17:32 Inactive
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: 3

🧹 Outside diff range and nitpick comments (5)
test/package/browser/template/README.md (1)

29-30: Consider adding test file references for completeness.

While the build script documentation is accurate, it would be helpful to also reference the corresponding test HTML files that use these bundles, particularly index-liveobjects.html which was mentioned in the AI summary.

Consider adding a note like:

  2. a bundle containing `src/index-liveobjects.ts` and ably-js.
  3. a bundle containing `src/index-modular.ts` and ably-js.
+ These bundles are used by corresponding HTML files (index-default.html, index-liveobjects.html, and index-modular.html) for testing.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

ably.d.ts (4)

2031-2033: Add JSDoc documentation for LiveObjects interface

The LiveObjects interface lacks documentation explaining its purpose and usage. Consider adding JSDoc comments to improve API documentation.

+/**
+ * Represents the LiveObjects functionality for a channel, providing access to live data structures.
+ */
 export declare interface LiveObjects {
+  /**
+   * Returns the root LiveMap instance for this channel.
+   * @returns A promise that resolves with the root LiveMap.
+   */
   getRoot(): Promise<LiveMap>;
 }

2035-2035: Address TODO comment regarding LiveObjects documentation

The TODO comment indicates missing documentation for the public API. This should be addressed before merging.

Would you like me to help generate comprehensive documentation for the LiveObjects public API? I can create a new GitHub issue to track this task.


2037-2040: Add JSDoc documentation for LiveMap interface

The LiveMap interface needs documentation for its methods and purpose.

+/**
+ * Represents a live map data structure that can be synchronized across clients.
+ */
 export declare interface LiveMap extends LiveObject<LiveMapUpdate> {
+  /**
+   * Retrieves a value from the map by key.
+   * @param key - The key to look up.
+   * @returns The value associated with the key, or undefined if not found.
+   */
   get(key: string): LiveObject | StateValue | undefined;
+  /**
+   * Returns the number of key-value pairs in the map.
+   * @returns The size of the map.
+   */
   size(): number;
 }

2056-2060: Improve type safety of subscription methods

The subscription methods could benefit from stronger typing.

Consider adding type parameters to better type the listener callbacks:

-export declare interface LiveObject<TUpdate extends LiveObjectUpdate = LiveObjectUpdate> {
+export declare interface LiveObject<TUpdate extends LiveObjectUpdate<T> = LiveObjectUpdate<any>, T = any> {
-  subscribe(listener: (update: TUpdate) => void): SubscribeResponse;
+  subscribe(listener: (update: TUpdate & { update: T }) => void): SubscribeResponse;
   unsubscribe(listener: (update: TUpdate) => void): void;
   unsubscribeAll(): void;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1fe3fd3 and 9da78a6.

📒 Files selected for processing (8)
  • ably.d.ts (1 hunks)
  • test/package/browser/template/README.md (2 hunks)
  • test/package/browser/template/package.json (1 hunks)
  • test/package/browser/template/server/resources/index-liveobjects.html (1 hunks)
  • test/package/browser/template/server/server.ts (1 hunks)
  • test/package/browser/template/src/index-liveobjects.ts (1 hunks)
  • test/package/browser/template/src/sandbox.ts (1 hunks)
  • test/package/browser/template/test/lib/package.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • test/package/browser/template/package.json
  • test/package/browser/template/server/resources/index-liveobjects.html
  • test/package/browser/template/server/server.ts
  • test/package/browser/template/src/sandbox.ts
  • test/package/browser/template/test/lib/package.test.ts
🧰 Additional context used
🪛 LanguageTool
test/package/browser/template/README.md

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

🪛 Biome (1.9.4)
test/package/browser/template/src/index-liveobjects.ts

[error] 27-27: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (5)
test/package/browser/template/src/index-liveobjects.ts (1)

1-3: LGTM: Imports are correctly structured

The necessary dependencies are properly imported for testing the LiveObjects plugin.

test/package/browser/template/README.md (2)

11-11: LGTM! Documentation accurately reflects the LiveObjects import.

The added line clearly documents how to import the LiveObjects plugin, which aligns with the PR objective of implementing LiveObjects plugin tests.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


Line range hint 1-30: Verify the completeness of TypeScript types documentation.

The PR objectives mention updates to ably.d.ts for LiveObjects' public API, but this README doesn't mention TypeScript type testing specifics for LiveObjects.

Let's check if there are any TypeScript-specific test files for LiveObjects:

✅ Verification successful

TypeScript types for LiveObjects are well-tested in the codebase

The index-liveobjects.ts file contains comprehensive TypeScript type testing for LiveObjects, including:

  • Type checking for LiveMap operations (root.get, root.size)
  • Exhaustive type checking for subscription callbacks
  • Type verification for LiveCounter operations and updates
  • Type assertions to ensure correct typing of values and updates

The README's statement about TypeScript type testing is accurate, as the implementation demonstrates thorough type checking through practical usage patterns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for TypeScript test files related to LiveObjects
fd -e ts -e tsx . | rg -i "liveobjects"

# Check if there are any type-specific tests
rg -i "typescript.*test.*liveobjects|liveobjects.*typescript.*test"

Length of output: 573


Script:

#!/bin/bash
# Let's check the content of index-liveobjects.ts to see how it tests TypeScript types
cat test/package/browser/template/src/index-liveobjects.ts

# Also check if there are any type assertions or type-related tests in the file
rg -A 5 "type|interface|declare" test/package/browser/template/src/index-liveobjects.ts

# Let's also check the content of liveobjects.d.ts to understand the type definitions
cat liveobjects.d.ts

Length of output: 3826

🧰 Tools
🪛 LanguageTool

[uncategorized] ~8-~8: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...tains three files, each of which import ably-js in different manners, and provide a way...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~10-~10: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...c/index-default.ts imports the default ably-js package (import { Realtime } from 'abl...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[style] ~12-~12: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...iveobjects'). - src/index-modular.ts imports the tree-shakable ably-js package (imp...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[uncategorized] ~12-~12: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...x-modular.ts imports the tree-shakable ably-js package (import { BaseRealtime, WebSoc...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[style] ~13-~13: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... 'ably/modular'). - src/ReactApp.tsx imports React hooks from the ably-js package (...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[uncategorized] ~13-~13: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ctApp.tsx imports React hooks from the ably-js package (import { useChannel } from 'a...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

ably.d.ts (2)

2046-2046: ⚠️ Potential issue

Replace Buffer with ArrayBuffer in StateValue type

The use of Buffer in browser environments could cause compatibility issues.

This issue was previously identified. Apply the suggested fix:

-export type StateValue = string | number | boolean | Buffer | Uint8Array;
+export type StateValue = string | number | boolean | ArrayBuffer | Uint8Array;

2062-2064: ⚠️ Potential issue

Make LiveObjectUpdate generic to improve type safety

Using any type defeats TypeScript's type safety. Consider making the interface generic.

This issue was previously identified. Apply the suggested fix:

-export declare interface LiveObjectUpdate {
-  update: any;
+export declare interface LiveObjectUpdate<T = any> {
+  update: T;
 }

@VeskeR VeskeR force-pushed the liveobjects/isolated-create-ops-and-vector-timeserials branch from 059e10b to 245b6a2 Compare November 22, 2024 17:38
@VeskeR VeskeR force-pushed the liveobjects/package-test branch from 9da78a6 to 426fd8d Compare November 22, 2024 17:50
@github-actions github-actions bot temporarily deployed to staging/pull/1921/bundle-report November 22, 2024 17:52 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/features November 22, 2024 17:52 Inactive
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: 0

🧹 Outside diff range and nitpick comments (12)
test/package/browser/template/src/index-liveobjects.ts (2)

19-30: Good use of exhaustiveness checking, but fix switch statement scoping

The use of a never type for exhaustiveness checking is a great practice as it ensures all possible update types are handled. However, the switch statement needs proper scoping as flagged by the static analysis.

Apply this diff to fix the scoping while preserving the exhaustiveness check:

  const { unsubscribe } = root.subscribe(({ update }) => {
    switch (update.someKey) {
      case 'removed':
      case 'updated':
        break;
      default: {
        // check all possible types are exhausted
        const shouldExhaustAllTypes: never = update.someKey;
        break;
      }
    }
  });
🧰 Tools
🪛 Biome (1.9.4)

[error] 27-27: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


33-33: Consider using type guard instead of type assertion

While the type assertion works for testing types, it's safer to use a type guard function to validate the LiveCounter type at runtime.

- const counter = root.get('randomKey') as Ably.LiveCounter | undefined;
+ const counter = root.get('randomKey');
+ const isLiveCounter = (value: unknown): value is Ably.LiveCounter => {
+   return value !== null && 
+     typeof value === 'object' && 
+     'value' in value &&
+     'increment' in value;
+ };
+ if (counter && isLiveCounter(counter)) {
+   // Now TypeScript knows counter is LiveCounter
+   counter.value();
+ }
test/package/browser/template/README.md (2)

29-30: Consider enhancing the build script documentation.

While the additions correctly document the new bundles, consider these improvements for better clarity:

  1. Use consistent list formatting
  2. Add brief descriptions of each bundle's purpose, especially for the LiveObjects and modular bundles
  1. a bundle containing `src/index-default.ts` and ably-js;
- 2. a bundle containing `src/index-liveobjects.ts` and ably-js.
- 3. a bundle containing `src/index-modular.ts` and ably-js.
+ 2. a bundle containing `src/index-liveobjects.ts` and ably-js for testing LiveObjects plugin integration;
+ 3. a bundle containing `src/index-modular.ts` and ably-js for testing tree-shakable imports;
🧰 Tools
🪛 LanguageTool

[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


Line range hint 1-30: Consider adding TypeScript types testing information.

The PR objectives mention validating TypeScript types for LiveObjects, but this isn't explicitly covered in the documentation. Consider adding a note about TypeScript types testing under the typecheck script section.

- `typecheck`: Type-checks the code that imports ably-js.
+ `typecheck`: Type-checks the code that imports ably-js, including validation of LiveObjects TypeScript types and interfaces.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~8-~8: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...tains three files, each of which import ably-js in different manners, and provide a way...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~10-~10: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...c/index-default.ts imports the default ably-js package (import { Realtime } from 'abl...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[style] ~12-~12: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...iveobjects'). - src/index-modular.ts imports the tree-shakable ably-js package (imp...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[uncategorized] ~12-~12: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...x-modular.ts imports the tree-shakable ably-js package (import { BaseRealtime, WebSoc...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[style] ~13-~13: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... 'ably/modular'). - src/ReactApp.tsx imports React hooks from the ably-js package (...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[uncategorized] ~13-~13: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ctApp.tsx imports React hooks from the ably-js package (import { useChannel } from 'a...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

ably.d.ts (8)

2031-2033: Add JSDoc documentation for LiveObjects interface and methods.

The interface and its method lack proper documentation. Consider adding:

  • Interface description explaining the purpose of LiveObjects
  • Method documentation explaining what getRoot() does and when to use it
+/**
+ * Provides access to LiveObjects functionality, allowing real-time state synchronization
+ * between clients.
+ */
 export declare interface LiveObjects {
+  /**
+   * Returns the root LiveMap object that serves as the entry point for LiveObjects state.
+   * @returns A promise that resolves with the root LiveMap instance.
+   */
   getRoot(): Promise<LiveMap>;
 }

2037-2040: Enhance LiveMap interface with documentation and type safety.

The interface needs documentation and could benefit from improved type safety:

  1. Add JSDoc documentation for interface and methods
  2. Consider making the interface generic to provide type-safe access to values
+/**
+ * Represents a synchronized map of key-value pairs that can be observed for changes.
+ * @template T The type of values stored in the map
+ */
-export declare interface LiveMap extends LiveObject<LiveMapUpdate> {
+export declare interface LiveMap<T = StateValue | LiveObject> extends LiveObject<LiveMapUpdate> {
+  /**
+   * Retrieves the value associated with the specified key.
+   * @param key The key to look up
+   * @returns The value if found, undefined otherwise
+   */
-  get(key: string): LiveObject | StateValue | undefined;
+  get(key: string): T | undefined;
+  /**
+   * Returns the number of key-value pairs in the map.
+   * @returns The size of the map
+   */
   size(): number;
 }

2042-2044: Add documentation and improve type safety of LiveMapUpdate interface.

The interface needs documentation and could have more specific types:

+/**
+ * Represents an update event for a LiveMap, indicating which keys were modified.
+ */
 export declare interface LiveMapUpdate extends LiveObjectUpdate {
+  /**
+   * A map of key names to their update type.
+   * - 'updated': The value for this key was updated
+   * - 'removed': The key was removed from the map
+   */
-  update: { [keyName: string]: 'updated' | 'removed' };
+  update: Record<string, 'updated' | 'removed'>;
 }

2048-2050: Add documentation for LiveCounter interface.

Add JSDoc documentation to explain the purpose and usage of the LiveCounter interface.

+/**
+ * Represents a synchronized counter that can be observed for changes.
+ * Useful for maintaining distributed counts across multiple clients.
+ */
 export declare interface LiveCounter extends LiveObject<LiveCounterUpdate> {
+  /**
+   * Returns the current value of the counter.
+   * @returns The current numeric value of the counter
+   */
   value(): number;
 }

2052-2054: Add documentation for LiveCounterUpdate interface.

Add JSDoc documentation to explain the update structure for counter changes.

+/**
+ * Represents an update event for a LiveCounter, containing the increment/decrement value.
+ */
 export declare interface LiveCounterUpdate extends LiveObjectUpdate {
+  /**
+   * The update payload containing the increment value.
+   * Positive values increment the counter, negative values decrement it.
+   */
   update: { inc: number };
 }

2056-2060: Enhance LiveObject interface with documentation and specific return types.

The interface needs documentation and could benefit from more specific types:

+/**
+ * Base interface for all live objects that can be observed for changes.
+ * @template TUpdate The type of update events emitted by this live object
+ */
 export declare interface LiveObject<TUpdate extends LiveObjectUpdate = LiveObjectUpdate> {
+  /**
+   * Subscribes to updates from this live object.
+   * @param listener The callback function that will be called with updates
+   * @returns A subscription response object that can be used to unsubscribe
+   */
   subscribe(listener: (update: TUpdate) => void): SubscribeResponse;
+  /**
+   * Removes a specific update listener.
+   * @param listener The callback function to remove
+   */
   unsubscribe(listener: (update: TUpdate) => void): void;
+  /**
+   * Removes all update listeners from this live object.
+   */
   unsubscribeAll(): void;
 }

2066-2068: Add documentation for SubscribeResponse interface.

Add JSDoc documentation to explain the purpose and usage of the subscription response.

+/**
+ * Represents a subscription to a live object, providing a way to unsubscribe.
+ */
 export declare interface SubscribeResponse {
+  /**
+   * Cancels the subscription, stopping further update notifications.
+   */
   unsubscribe(): void;
 }

2035-2035: Address TODO comment about documenting public API.

The TODO comment indicates missing documentation for the LiveObjects public API. This should be addressed before merging, as proper documentation is crucial for the public API.

Would you like me to help generate comprehensive documentation for the LiveObjects public API?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 9da78a6 and 426fd8d.

📒 Files selected for processing (8)
  • ably.d.ts (1 hunks)
  • test/package/browser/template/README.md (2 hunks)
  • test/package/browser/template/package.json (1 hunks)
  • test/package/browser/template/server/resources/index-liveobjects.html (1 hunks)
  • test/package/browser/template/server/server.ts (1 hunks)
  • test/package/browser/template/src/index-liveobjects.ts (1 hunks)
  • test/package/browser/template/src/sandbox.ts (1 hunks)
  • test/package/browser/template/test/lib/package.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • test/package/browser/template/package.json
  • test/package/browser/template/server/resources/index-liveobjects.html
  • test/package/browser/template/server/server.ts
  • test/package/browser/template/src/sandbox.ts
  • test/package/browser/template/test/lib/package.test.ts
🧰 Additional context used
🪛 LanguageTool
test/package/browser/template/README.md

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

🪛 Biome (1.9.4)
test/package/browser/template/src/index-liveobjects.ts

[error] 27-27: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (3)
test/package/browser/template/README.md (1)

11-11: LGTM! Import example is well documented.

The added LiveObjects import example is clear, consistent with other examples, and correctly documents the import syntax for the LiveObjects plugin.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

ably.d.ts (2)

2046-2046: Reiterating past review comment about Buffer usage.

The previous review comment about replacing Buffer with ArrayBuffer is still valid and should be addressed.


2062-2064: Reiterating past review comment about 'any' type usage.

The previous review comment about avoiding the 'any' type is still valid and should be addressed.

Base automatically changed from liveobjects/isolated-create-ops-and-vector-timeserials to integration/liveobjects November 26, 2024 09:30
@VeskeR VeskeR force-pushed the liveobjects/package-test branch from 32838f3 to fc7fe8b Compare November 28, 2024 04:56
@github-actions github-actions bot temporarily deployed to staging/pull/1921/bundle-report November 28, 2024 04:57 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/features November 28, 2024 04:57 Inactive
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: 0

🧹 Outside diff range and nitpick comments (1)
test/package/browser/template/README.md (1)

29-30: Consider clarifying the build script documentation.

While the bundle list is accurate, consider updating the introductory text "This directory exposes three package scripts" to better distinguish between the number of package scripts (build, test, typecheck) and the number of bundles created by the build script (now three instead of two).

Here's a suggested improvement:

- This directory exposes three package scripts that are to be used for testing:
+ This directory exposes the following package scripts for testing:
🧰 Tools
🪛 LanguageTool

[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 32838f3 and fc7fe8b.

📒 Files selected for processing (8)
  • test/package/browser/template/README.md (2 hunks)
  • test/package/browser/template/package.json (1 hunks)
  • test/package/browser/template/server/resources/index-liveobjects.html (1 hunks)
  • test/package/browser/template/server/server.ts (1 hunks)
  • test/package/browser/template/src/index-liveobjects.ts (1 hunks)
  • test/package/browser/template/src/sandbox.ts (1 hunks)
  • test/package/browser/template/src/tsconfig.json (1 hunks)
  • test/package/browser/template/test/lib/package.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • test/package/browser/template/package.json
  • test/package/browser/template/server/resources/index-liveobjects.html
  • test/package/browser/template/server/server.ts
  • test/package/browser/template/src/sandbox.ts
  • test/package/browser/template/test/lib/package.test.ts
🧰 Additional context used
🪛 LanguageTool
test/package/browser/template/README.md

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

🪛 Biome (1.9.4)
test/package/browser/template/src/index-liveobjects.ts

[error] 29-29: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (8)
test/package/browser/template/src/tsconfig.json (2)

2-5: LGTM: Improved formatting of include array

The array formatting enhances readability while maintaining the same functionality.


10-10: Verify impact of moduleResolution change

Changing moduleResolution from "bundler" to "node" could affect how the LiveObjects plugin and its dependencies are resolved. Please ensure:

  1. The LiveObjects plugin imports work correctly in the test environment
  2. All @ably package imports resolve properly
  3. TypeScript type definitions are correctly resolved

Let's verify the module resolution configuration across the project:

✅ Verification successful

No impact from moduleResolution change

The change from "bundler" to "node" moduleResolution in test/package/browser/template/src/tsconfig.json is safe because:

  1. Both tsconfig files in the project already use "node" moduleResolution
  2. The LiveObjects plugin imports work correctly with relative paths and package imports
  3. The only @ably package import is for msgpack-js which uses a standard Node.js resolution pattern
  4. Test files demonstrate successful LiveObjects plugin imports using the standard Node.js resolution
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential module resolution issues

# Check for any relative imports that might be affected
echo "Checking for relative imports in TypeScript files:"
rg -t ts "from '\.\./|from '\./" -A 2

# Check for LiveObjects-related imports
echo "Checking LiveObjects-related imports:"
rg -t ts "LiveObjects|@ably/.*live-objects" -A 2

# Check other tsconfig files for consistency
echo "Checking other tsconfig files for moduleResolution settings:"
fd tsconfig.json --exec grep -l "moduleResolution"

Length of output: 98065


Script:

#!/bin/bash
# Let's verify the module resolution configuration and its impact

# Check the content of the tsconfig files that have moduleResolution
echo "Content of test/package/browser/template/src/tsconfig.json:"
cat test/package/browser/template/src/tsconfig.json

echo -e "\nContent of src/platform/react-hooks/tsconfig.json:"
cat src/platform/react-hooks/tsconfig.json

# Check for any @ably package imports
echo -e "\nChecking @ably package imports:"
rg -t ts "@ably" -A 2

# Check for any LiveObjects plugin imports in test files
echo -e "\nChecking LiveObjects imports in test files:"
rg -t ts "LiveObjects" test/ -A 2

Length of output: 2784

test/package/browser/template/src/index-liveobjects.ts (5)

5-8: ⚠️ Potential issue

Add cleanup for Realtime instance

The test should properly clean up resources by closing the Realtime instance after tests complete to prevent resource leaks.

Apply this diff:

 globalThis.testAblyPackage = async function () {
-  const key = await createSandboxAblyAPIKey({ featureFlags: ['enableChannelState'] });
-  const realtime = new Ably.Realtime({ key, environment: 'sandbox', plugins: { LiveObjects } });
+  let realtime: Ably.Realtime | undefined;
+  try {
+    const key = await createSandboxAblyAPIKey({ featureFlags: ['enableChannelState'] });
+    realtime = new Ably.Realtime({ key, environment: 'sandbox', plugins: { LiveObjects } });

And at the end of the function:

+  } finally {
+    await realtime?.close();
+  }
 };

10-15: ⚠️ Potential issue

Add error handling for channel attachment and root access

While the channel attachment is performed, there's no error handling for either the attachment or root access operations.

Apply this diff:

   const channel = realtime.channels.get('channel', { modes: ['STATE_SUBSCRIBE', 'STATE_PUBLISH'] });
-  // check liveObjects can be accessed
   const liveObjects = channel.liveObjects;
-  await channel.attach();
+  try {
+    await new Promise<void>((resolve, reject) => {
+      channel.once('attached', () => resolve());
+      channel.once('failed', (err) => reject(err));
+    });
+  } catch (error) {
+    console.error('Channel attachment failed:', error);
+    throw error;
+  }
+
   // root should be a LiveMap object
-  const root: Ably.LiveMap = await liveObjects.getRoot();
+  let root: Ably.LiveMap;
+  try {
+    root = await liveObjects.getRoot();
+  } catch (error) {
+    console.error('Failed to get root:', error);
+    throw error;
+  }

17-19: ⚠️ Potential issue

Add runtime assertions for LiveMap operations

The current test only verifies TypeScript types without validating actual behavior.

Apply this diff:

   // check root is recognized as LiveMap TypeScript type
-  root.get('someKey');
-  root.size();
+  const testKey = 'testKey';
+  const testValue = { data: 'test' };
+  
+  await root.set(testKey, testValue);
+  const retrievedValue = root.get(testKey);
+  console.assert(
+    JSON.stringify(retrievedValue) === JSON.stringify(testValue),
+    'Retrieved value should match set value'
+  );
+  
+  const size = root.size();
+  console.assert(size > 0, 'Map should not be empty after setting a value');

21-32: ⚠️ Potential issue

Fix switch statement scoping and add error handling

The switch statement has a scoping issue that could lead to variable leakage, and the subscription cleanup should be handled in a try-finally block.

Apply this diff:

   // check LiveMap subscription callback has correct TypeScript types
-  const { unsubscribe } = root.subscribe(({ update }) => {
-    switch (update.someKey) {
-      case 'removed':
-      case 'updated':
-        break;
-      default:
-        // check all possible types are exhausted
-        const shouldExhaustAllTypes: never = update.someKey;
-    }
-  });
-  unsubscribe();
+  let unsubscribe: (() => void) | undefined;
+  try {
+    unsubscribe = root.subscribe(({ update }) => {
+      switch (update.someKey) {
+        case 'removed':
+        case 'updated':
+          break;
+        default: {
+          // check all possible types are exhausted
+          const shouldExhaustAllTypes: never = update.someKey;
+          break;
+        }
+      }
+    }).unsubscribe;
+  } finally {
+    unsubscribe?.();
+  }
🧰 Tools
🪛 Biome (1.9.4)

[error] 29-29: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


34-42: ⚠️ Potential issue

Add actual LiveCounter testing

The current implementation only tests TypeScript types without creating and testing an actual counter instance.

Apply this diff:

   // check LiveCounter types also behave as expected
-  const counter = root.get('randomKey') as Ably.LiveCounter | undefined;
-  // use nullish coalescing as we didn't actually create a counter object on the root,
-  // so the next calls would fail. we only need to check that TypeScript types work
-  const value: number = counter?.value();
-  const counterSubscribeResponse = counter?.subscribe(({ update }) => {
-    const shouldBeANumber: number = update.inc;
-  });
-  counterSubscribeResponse?.unsubscribe();
+  try {
+    const counterKey = 'testCounter';
+    const counter = await root.createCounter(counterKey, { initial: 0 });
+    
+    // Test counter operations
+    await counter.increment(5);
+    console.assert(counter.value() === 5, 'Counter value should be 5');
+    
+    // Test counter subscription
+    let unsubscribe: (() => void) | undefined;
+    try {
+      unsubscribe = counter.subscribe(({ update }) => {
+        console.assert(typeof update.inc === 'number', 'Increment value should be a number');
+      }).unsubscribe;
+      
+      await counter.increment(3);
+    } finally {
+      unsubscribe?.();
+    }
+    
+    // Cleanup
+    await root.delete(counterKey);
+  } catch (error) {
+    console.error('Failed to test counter:', error);
+    throw error;
+  }
test/package/browser/template/README.md (1)

11-11: LGTM! Clear documentation of LiveObjects import.

The added documentation clearly explains how to import the LiveObjects plugin, maintaining consistency with the existing documentation style.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

@VeskeR VeskeR force-pushed the liveobjects/read-api-docs branch from bf0ffeb to 8471516 Compare November 28, 2024 05:13
@VeskeR VeskeR force-pushed the liveobjects/package-test branch from fc7fe8b to 1e5634a Compare November 28, 2024 05:14
@github-actions github-actions bot temporarily deployed to staging/pull/1921/bundle-report November 28, 2024 05:14 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/typedoc November 28, 2024 05:14 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/features November 28, 2024 05:14 Inactive
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: 0

🧹 Outside diff range and nitpick comments (3)
test/package/browser/template/src/index-liveobjects.ts (1)

5-43: Improve test structure and organization

The current test combines all checks in a single function without clear separation between test cases. Consider restructuring the test for better maintainability:

  1. Separate test cases into distinct async functions
  2. Add descriptive names for each test case
  3. Include setup and teardown for each test case

Example structure:

async function testLiveMapTypeChecks() {
  // LiveMap type checking tests
}

async function testLiveMapOperations() {
  // LiveMap operation tests
}

async function testLiveCounterOperations() {
  // LiveCounter operation tests
}

globalThis.testAblyPackage = async function () {
  await testLiveMapTypeChecks();
  await testLiveMapOperations();
  await testLiveCounterOperations();
};
🧰 Tools
🪛 Biome (1.9.4)

[error] 29-29: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

test/package/browser/template/README.md (2)

29-30: Consider improving list formatting consistency.

While the content is correct, consider adjusting the formatting to maintain consistent indentation with the first numbered item. This would improve readability:

  1. a bundle containing `src/index-default.ts` and ably-js;
- 2. a bundle containing `src/index-liveobjects.ts` and ably-js.
- 3. a bundle containing `src/index-modular.ts` and ably-js.
+ 2. a bundle containing `src/index-liveobjects.ts` and ably-js;
+ 3. a bundle containing `src/index-modular.ts` and ably-js.

Also note the consistent use of semicolons at the end of each list item.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


11-11: Consider adding a note about documentation status.

Since the PR mentions that documentation for LiveObjects is not yet available, it would be helpful to add a brief note indicating this is a preview/beta feature or that documentation is forthcoming. This would help set proper expectations for users.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between fc7fe8b and 1e5634a.

📒 Files selected for processing (8)
  • test/package/browser/template/README.md (2 hunks)
  • test/package/browser/template/package.json (1 hunks)
  • test/package/browser/template/server/resources/index-liveobjects.html (1 hunks)
  • test/package/browser/template/server/server.ts (1 hunks)
  • test/package/browser/template/src/index-liveobjects.ts (1 hunks)
  • test/package/browser/template/src/sandbox.ts (1 hunks)
  • test/package/browser/template/src/tsconfig.json (1 hunks)
  • test/package/browser/template/test/lib/package.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • test/package/browser/template/package.json
  • test/package/browser/template/server/resources/index-liveobjects.html
  • test/package/browser/template/server/server.ts
  • test/package/browser/template/src/sandbox.ts
  • test/package/browser/template/src/tsconfig.json
  • test/package/browser/template/test/lib/package.test.ts
🧰 Additional context used
🪛 LanguageTool
test/package/browser/template/README.md

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

🪛 Biome (1.9.4)
test/package/browser/template/src/index-liveobjects.ts

[error] 29-29: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (7)
test/package/browser/template/src/index-liveobjects.ts (6)

1-3: LGTM!

The imports are correctly structured and include all necessary dependencies for testing the LiveObjects plugin.


5-10: Add cleanup for Realtime instance

The test should properly clean up resources by closing the Realtime instance after tests complete.


11-15: Add channel connection handling and error handling

The channel setup should include connection state handling and proper error handling for root access.


17-19: Add runtime assertions for LiveMap operations

The current test only verifies TypeScript types. Add actual runtime assertions to verify the behavior.


34-42: Add actual LiveCounter testing

The current implementation only tests TypeScript types without creating and testing an actual counter.


21-32: ⚠️ Potential issue

Fix switch statement scoping issue

The shouldExhaustAllTypes declaration in the default case can be erroneously accessed from other cases. This could lead to unexpected behavior.

Apply this fix to properly scope the declaration:

   const { unsubscribe } = root.subscribe(({ update }) => {
     switch (update.someKey) {
       case 'removed':
       case 'updated':
         break;
       default: {
         // check all possible types are exhausted
         const shouldExhaustAllTypes: never = update.someKey;
         break;
       }
     }
   });

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 29-29: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

test/package/browser/template/README.md (1)

11-11: LGTM! Clear documentation of LiveObjects import.

The added documentation clearly shows how to import the LiveObjects plugin, which aligns well with the PR's objective of implementing LiveObjects plugin testing.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

@VeskeR VeskeR force-pushed the liveobjects/package-test branch from 1e5634a to 5d72d44 Compare November 28, 2024 05:52
@github-actions github-actions bot temporarily deployed to staging/pull/1921/bundle-report November 28, 2024 05:53 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/features November 28, 2024 05:53 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/typedoc November 28, 2024 05:53 Inactive
@VeskeR VeskeR force-pushed the liveobjects/read-api-docs branch from 8471516 to 0b4b1e4 Compare November 28, 2024 06:43
@VeskeR VeskeR force-pushed the liveobjects/package-test branch from 5d72d44 to 028eec3 Compare November 28, 2024 06:44
@github-actions github-actions bot temporarily deployed to staging/pull/1921/bundle-report November 28, 2024 06:45 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/features November 28, 2024 06:45 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1921/typedoc November 28, 2024 06:45 Inactive
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: 0

🧹 Outside diff range and nitpick comments (2)
test/package/browser/template/src/index-liveobjects.ts (1)

1-43: Enhance test coverage with comprehensive functionality testing

While the current implementation verifies TypeScript types, it lacks comprehensive testing of the actual LiveObjects functionality. Consider adding:

  1. Actual data operations and verifications
  2. Error scenarios testing
  3. State transition testing
  4. Concurrent operations testing
  5. Network condition handling

Consider structuring the test into distinct sections:

  1. Setup and initialization
  2. Basic operations (get, set, delete)
  3. Subscription and updates
  4. Counter operations
  5. Error scenarios
  6. Cleanup

This structure will make the test more maintainable and easier to debug when issues occur.

🧰 Tools
🪛 Biome (1.9.4)

[error] 29-29: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

test/package/browser/template/README.md (1)

29-30: Consider improving the build script documentation format.

While the content is accurate, the current numbering format (2. and 3. on separate lines) might be confusing. Consider using a more consistent format:

  1. a bundle containing `src/index-default.ts` and ably-js;
- 2. a bundle containing `src/index-liveobjects.ts` and ably-js.
- 3. a bundle containing `src/index-modular.ts` and ably-js.
+ 2. a bundle containing `src/index-liveobjects.ts` and ably-js;
+ 3. a bundle containing `src/index-modular.ts` and ably-js.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5d72d44 and 028eec3.

📒 Files selected for processing (8)
  • test/package/browser/template/README.md (2 hunks)
  • test/package/browser/template/package.json (1 hunks)
  • test/package/browser/template/server/resources/index-liveobjects.html (1 hunks)
  • test/package/browser/template/server/server.ts (1 hunks)
  • test/package/browser/template/src/index-liveobjects.ts (1 hunks)
  • test/package/browser/template/src/sandbox.ts (1 hunks)
  • test/package/browser/template/src/tsconfig.json (1 hunks)
  • test/package/browser/template/test/lib/package.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • test/package/browser/template/package.json
  • test/package/browser/template/server/resources/index-liveobjects.html
  • test/package/browser/template/server/server.ts
  • test/package/browser/template/src/sandbox.ts
  • test/package/browser/template/src/tsconfig.json
  • test/package/browser/template/test/lib/package.test.ts
🧰 Additional context used
🪛 LanguageTool
test/package/browser/template/README.md

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~29-~29: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...ntaining src/index-liveobjects.ts and ably-js. 3. a bundle containing `src/index-mo...

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[uncategorized] ~30-~30: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...e containing src/index-modular.ts and ably-js. - test: Using the bundles created by...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

🪛 Biome (1.9.4)
test/package/browser/template/src/index-liveobjects.ts

[error] 29-29: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (6)
test/package/browser/template/src/index-liveobjects.ts (5)

5-10: Add proper cleanup and error handling for initialization

The initialization should include proper cleanup of the Realtime instance and error handling.

Previous review comments already suggested adding cleanup and error handling for the Realtime instance. The same concerns apply here.


11-16: Add error handling for channel attachment and root access

While channel.attach() is called, there's no handling of attachment failures or errors during root access.

Previous review comments already suggested adding channel connection handling and error handling for root access. The same concerns apply here.


17-19: Add runtime assertions for LiveMap operations

Previous review comments already suggested adding runtime assertions for LiveMap operations. The same concerns apply here.


34-43: Add actual LiveCounter testing

Previous review comments already suggested adding actual LiveCounter testing. The same concerns apply here.


21-33: 🛠️ Refactor suggestion

Fix switch statement scoping and add subscription testing

Previous review comments already suggested fixing the switch statement scoping and adding error handling. The same concerns apply here.

Additionally:

Add actual subscription testing to verify the functionality:

   const { unsubscribe } = root.subscribe(({ update }) => {
+    console.log('Received update:', update);
     switch (update.someKey) {
       case 'removed':
+        console.assert(update.oldValue !== undefined, 'Removed update should have oldValue');
+        break;
       case 'updated':
+        console.assert(update.newValue !== undefined, 'Updated update should have newValue');
         break;
       default: {
         // check all possible types are exhausted
         const shouldExhaustAllTypes: never = update.someKey;
+        break;
       }
     }
   });
+  
+  // Trigger updates to test subscription
+  await root.set('testKey', 'testValue');
+  await root.delete('testKey');
🧰 Tools
🪛 Biome (1.9.4)

[error] 29-29: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

test/package/browser/template/README.md (1)

11-11: LGTM! Clear documentation of LiveObjects import.

The added documentation clearly explains how to import the LiveObjects plugin, maintaining consistency with the existing documentation style and aligning with the PR objectives.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~11-~11: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...liveobjects.ts imports the LiveObjects ably-js plugin (import LiveObjects from 'ably/...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

Copy link
Contributor

@mschristensen mschristensen left a comment

Choose a reason for hiding this comment

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

Approving pending #1922 to be merged in

Base automatically changed from liveobjects/read-api-docs to integration/liveobjects November 29, 2024 06:22
Test LiveObjects plugin can be imported and provided to the Ably client,
and that TypeScript types for LiveObjects work as expected.
`moduleResolution` must be set to `node` as `resolveJsonModule: true`
cannot be used otherwise.
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.

2 participants