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

[EDU-1691] - Add pub-sub rewind example #2436

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

GregHolmes
Copy link
Contributor

@GregHolmes GregHolmes commented Feb 20, 2025

This PR contains the two code samples for the new Examples section we are creating. It contains a Typescript and a React version for Pub Sub Rewind.

The README within each directory /examples/pub-sub-rewind/javascript and /examples/pub-sub-rewind/react contains information on how to get these running.

Summary by CodeRabbit

  • New Features

    • Introduced interactive demos showcasing real-time messaging with a rewind option, allowing users to view historical messages alongside live betting odds updates.
    • Enhanced user interfaces provide dynamic match simulations and live game updates.
  • Documentation

    • Added comprehensive setup guides with step-by-step instructions for both JavaScript and React demos to ensure a smooth experience.

@GregHolmes GregHolmes self-assigned this Feb 20, 2025
Copy link

coderabbitai bot commented Feb 20, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

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

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

Walkthrough

This pull request introduces a full demo of a Pub/Sub rewind channel implemented in both JavaScript and React. It adds new environment variables and configuration files (for Vite, Next.js, Tailwind CSS, TypeScript, and ESLint), along with HTML, TypeScript, and React component implementations that utilize Ably’s real-time messaging. Comprehensive documentation is provided for both demos, ensuring that users understand how to set up, run, and interact with the live data updates and rewind functionalities.

Changes

Files Change Summary
examples/pub-sub-rewind/javascript/.env.example, .../.gitignore, package.json, vite.config.ts, vite-env.d.ts, tsconfig.json, tailwind.config.js Added environment variable (VITE_PUBLIC_ABLY_KEY), gitignore patterns, project metadata, and key configuration files for Vite, TypeScript, and Tailwind CSS for the JavaScript demo.
examples/pub-sub-rewind/javascript/index.html, src/script.ts, src/styles.css Created the HTML template, implemented real-time betting odds logic using Ably (including functions for UI updates and odds history), and added Tailwind-based styling.
examples/pub-sub-rewind/javascript/README.md, page.md Included user and developer documentation detailing setup, configuration, and usage instructions for the JavaScript Pub/Sub rewind feature.
examples/pub-sub-rewind/react/.env.example, .../.eslintrc.json, .../.gitignore, next.config.ts, package.json, postcss.config.mjs, tsconfig.json, tailwind.config.ts Added environment variable (NEXT_PUBLIC_ABLY_KEY), ESLint, Git ignore, Next.js, PostCSS, and TypeScript configurations, along with project metadata for the React demo.
examples/pub-sub-rewind/react/src/app/layout.tsx, src/app/odds/page.tsx, src/app/page.tsx, styles/styles.css Developed the React application layout and pages: a RootLayout component, dynamic live match odds components (including LiveMatch and MatchWrapper), and home page logic for simulating odds updates with Ably integration, complemented by Tailwind CSS styling.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Browser as Browser App (JS)
    participant Ably as Ably Service
    participant UI as UI Components

    User->>Browser: Load application
    Browser->>Ably: Connect using VITE_PUBLIC_ABLY_KEY
    Browser->>Ably: Subscribe to channel
    Ably-->>Browser: Send odds update message
    Browser->>UI: Update current odds & history
    UI-->>User: Display updated match data
Loading
sequenceDiagram
    participant User as User
    participant Browser as Browser App (React)
    participant Ably as Ably Service
    participant Router as Next.js Router

    User->>Browser: Click "Load Odds" button
    Browser->>Ably: Preload odds history with NEXT_PUBLIC_ABLY_KEY
    Ably-->>Browser: Receive match odds updates
    Browser->>UI: Update LiveMatch component with new odds
    Browser->>Router: Redirect to updated odds page
    UI-->>User: Display real-time match updates
Loading

Possibly related PRs

Suggested reviewers

  • kennethkalmer
  • jamiehenson
  • m-hulbert

Poem

I'm a bunny with code in my feet,
Hop-ping through changes oh so neat.
Ably keys and channel streams,
Real-time odds and lively dreams.
With Tailwind style and TypeScript charm,
Our rewind demo brings no harm.
🐰 Hooray for code that makes hearts warm!


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

@ably-ci ably-ci temporarily deployed to ably-docs-edu-1691-exam-qpfg2s February 20, 2025 14:22 Inactive
@GregHolmes GregHolmes force-pushed the EDU-1691-Example-Pub-Sub-History-Rewind branch from ced81c4 to e228bbb Compare February 25, 2025 15:57
@GregHolmes GregHolmes force-pushed the EDU-1691-Example-Pub-Sub-History-Rewind branch from e228bbb to ca84dc8 Compare March 5, 2025 11:22
@GregHolmes GregHolmes changed the title [EDU-1691] - Add pub-sub history rewind example [EDU-1691] - Add pub-sub rewind example Mar 5, 2025
@GregHolmes
Copy link
Contributor Author

@coderabbitai full review

Copy link

coderabbitai bot commented Mar 5, 2025

✅ Actions performed

Full review triggered.

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: 11

🧹 Nitpick comments (22)
examples/pub-sub-rewind/react/.env.example (1)

1-1: Appropriate naming convention for Next.js environment variable

The environment variable follows Next.js naming convention with the NEXT_PUBLIC_ prefix, indicating it will be exposed to the browser. This is correct for client-side Ably API key usage.

Consider adding a brief comment explaining how to obtain an Ably API key for new developers who might be using this example.

-NEXT_PUBLIC_ABLY_KEY=
+# Get your Ably API key from https://ably.com/dashboard
+NEXT_PUBLIC_ABLY_KEY=
examples/pub-sub-rewind/javascript/.env.example (1)

1-1: Appropriate naming convention for Vite environment variable

The environment variable correctly follows Vite's naming convention with the VITE_ prefix, ensuring it will be accessible in client-side code.

Consider adding a brief comment explaining how to obtain an Ably API key for new developers.

-VITE_PUBLIC_ABLY_KEY=
+# Get your Ably API key from https://ably.com/dashboard
+VITE_PUBLIC_ABLY_KEY=
examples/pub-sub-rewind/react/next.config.ts (1)

1-8: Next.js Config File is Correct

The configuration uses the correct type import and structure. The placeholder comment ("/* config options here */") indicates where project-specific options can be added later. Consider replacing it with actual options once requirements are finalized.

examples/pub-sub-rewind/javascript/vite.config.ts (1)

1-12: Address Vite config syntax according to project style guide.

The configuration is correctly set up with TailwindCSS and Autoprefixer, which is appropriate for a styling pipeline. However, there are formatting issues that should be addressed to match the project's style guide.

-import { defineConfig } from 'vite'
+import { defineConfig } from 'vite';
 
 export default defineConfig({
   css: {
     postcss: {
       plugins: [
-        require('tailwindcss'),
-        require('autoprefixer'),
+        require('tailwindcss'), require('autoprefixer')
       ],
-    }
-  }
-})
+    },
+  },
+});
🧰 Tools
🪛 ESLint

[error] 1-1: Insert ;

(prettier/prettier)


[error] 6-9: Replace ⏎········require('tailwindcss'),⏎········require('autoprefixer'),⏎······ with require('tailwindcss'),·require('autoprefixer')

(prettier/prettier)


[error] 10-10: Insert ,

(prettier/prettier)


[error] 11-11: Insert ,

(prettier/prettier)


[error] 12-12: Insert ;⏎

(prettier/prettier)

examples/pub-sub-rewind/javascript/README.md (1)

25-25: Consider adding a comma after ".env.local" for better readability.

-4. In `.env.local` update the value of `VITE_PUBLIC_ABLY_KEY` to be your Ably API key.
+4. In `.env.local`, update the value of `VITE_PUBLIC_ABLY_KEY` to be your Ably API key.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~25-~25: Possible missing comma found.
Context: ...mple .env.local ``` 4. In .env.local update the value of `VITE_PUBLIC_ABLY_KEY` to ...

(AI_HYDRA_LEO_MISSING_COMMA)


[style] ~25-~25: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...ue of VITE_PUBLIC_ABLY_KEY to be your Ably API key. 5. Install dependencies: ```...

(ADVERB_REPETITION_PREMIUM)

examples/pub-sub-rewind/javascript/.gitignore (1)

12-14: Consider removing Next.js specific patterns for a Vite project.

The file includes Next.js specific patterns (/.next/, /out/), but this appears to be a Vite project based on the presence of vite.config.ts. If this example doesn't use Next.js, these patterns could be removed.

-# next.js
-/.next/
-/out/
examples/pub-sub-rewind/react/src/app/layout.tsx (1)

15-17: Fix indentation in the body element.

The children element has inconsistent indentation compared to the rest of the component structure.

     <html lang="en">
       <body className={inter.className}>
-          {children}
+        {children}
       </body>
     </html>
examples/pub-sub-rewind/javascript/tsconfig.json (1)

8-8: Consider using ESM modules instead of CommonJS for browser applications.

While commonjs works, modern browser applications typically use ES modules. This might be intentional if your build process transforms the modules, but if not, consider changing to:

-      "module": "commonjs",
+      "module": "ESNext",

This would better align with modern web development practices and potentially enable better tree-shaking.

examples/pub-sub-rewind/react/README.md (1)

39-39: Consider adding more context about the demo functionality.

The README explains how to set up and run the example but doesn't describe what users will see or how to interact with the demo once it's running. Consider adding a brief section explaining:

  • What the interface looks like
  • How to use the rewind feature in the demo
  • What interactions are available
  • Any example messages that might be displayed

This would help users better understand what they're seeing when they access the application.

examples/pub-sub-rewind/javascript/index.html (1)

1-89: HTML Markup is Clean and Structured
The file provides a clear structure with distinct sections (landing and game interface) and uses Tailwind CSS classes effectively. Consider enhancing semantic accessibility (e.g., using <main> or <section> tags) and ARIA attributes where appropriate to further improve accessibility.

examples/pub-sub-rewind/page.md (3)

1-10: Documentation Introduction – Clarity and Redundancy
The introductory section clearly explains the rewind feature. However, note that phrases regarding retrieving historical messages appear a bit redundant (e.g., lines 5 and 7). Consider streamlining the text for improved clarity and conciseness.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~5-~5: Possible missing article found.
Context: ... start working in your application with context of what happened before they went joine...

(AI_HYDRA_LEO_MISSING_THE)


11-24: Example Briefs for React and JavaScript
The React and JavaScript briefs provide valuable contextual information and link to relevant Ably documentation. A minor suggestion: review punctuation and phrasing (e.g., ensure that any informal markers like // React brief are either styled as proper markdown comments or integrated into the documentation narrative) for consistency.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~17-~17: Loose punctuation mark.
Context: ...ocs/getting-started/react#ably-provider): initializes and manages a shared pub/su...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~18-~18: Loose punctuation mark.
Context: .../getting-started/react#channel-provider): manages the state and functionality of ...

(UNLIKELY_OPENING_PUNCTUATION)


112-119: CodeSandbox Instructions – Avoid Repetitive Phrasing
Both the React and JavaScript CodeSandbox instructions repeat nearly identical steps for renaming the environment file and updating the API key variable. Consider consolidating these instructions or rephrasing to avoid adverb repetition (as noted by static analysis). For example, you might reword to:

"In CodeSandbox, rename the .env.example file to .env.local and update the corresponding API key variable with your Ably API key."

🧰 Tools
🪛 LanguageTool

[style] ~114-~114: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...T_PUBLIC_ABLY_KEY` variable to use your Ably API key. // Javascript In CodeSandbox...

(ADVERB_REPETITION_PREMIUM)


[style] ~118-~118: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...E_PUBLIC_ABLY_KEY` variable to use your Ably API key.

(ADVERB_REPETITION_PREMIUM)

examples/pub-sub-rewind/react/src/app/page.tsx (3)

17-20: Add error handling for Ably client initialization.

The Ably client initialization lacks error handling, which might cause silent failures if the connection cannot be established.

  const client = new Ably.Realtime({
    key: process.env.NEXT_PUBLIC_ABLY_KEY,
    clientId,
+   autoConnect: true,
  });
+
+  client.connection.on('failed', (err) => {
+    console.error('Ably connection failed:', err);
+    setIsLoading(false);
+  });

45-75: Add cleanup for asynchronous operations to prevent memory leaks.

The asynchronous loop and timeout operations should be properly cleaned up if the component unmounts during their execution.

  const preloadOddsHistory = async () => {
    setIsLoading(true);
+    let isMounted = true; // Flag to track if component is mounted
    const clientId = faker.person.firstName();
    const client = new Ably.Realtime({
      key: process.env.NEXT_PUBLIC_ABLY_KEY,
      clientId,
    });

    const channel = client.channels.get(channelName);
    const homeTeam = "Royal Knights";
    const awayTeam = "North Rangers";

    // ... [rest of the code remains the same]

    for (let i = 0; i < 10; i++) {
+      if (!isMounted) break; // Stop if component unmounted
      // ... [loop content remains the same]
      
      // Adjust timeout handling
      await new Promise(resolve => {
+        const timeoutId = setTimeout(resolve, 1000);
+        // Allow for cleanup if component unmounts
+        return () => clearTimeout(timeoutId);
      });
    }

+    if (isMounted) {
      router.push(`/odds?name=${encodeURIComponent(channelName)}`);
+    }
+    
+    // Return cleanup function
+    return () => {
+      isMounted = false;
+      client.close(); // Close Ably connection
+    };
  };

Then in your component:

+ useEffect(() => {
+   let cleanup;
+   if (isLoading) {
+     cleanup = preloadOddsHistory();
+   }
+   return () => {
+     if (cleanup) cleanup();
+   };
+ }, [isLoading]);

8-102: Extract the odds update logic into a reusable utility function.

The odds update logic is duplicated across the application (in both page.tsx and odds/page.tsx). Extract this into a utility function to improve maintainability.

Consider creating a utility file utils/oddsUpdate.ts with:

export interface MatchOdds {
  match: {
    homeTeam: string;
    awayTeam: string;
    timestamp: string;
    score: string;
    matchOdds: {
      homeWin: string;
      draw: string;
      awayWin: string;
    };
    nextGoal: {
      [key: string]: string;
    };
  };
}

export function updateRandomOdds(currentOdds: MatchOdds): MatchOdds {
  const markets = ['homeWin', 'draw', 'awayWin', 'nextGoal'];
  const numMarketsToUpdate = Math.floor(Math.random() * 2) + 1;
  const marketsToUpdate = markets.sort(() => 0.5 - Math.random()).slice(0, numMarketsToUpdate);

  const newOdds = { ...currentOdds };

  marketsToUpdate.forEach(market => {
    if (market === 'nextGoal') {
      const team = Object.keys(newOdds.match.nextGoal)[Math.floor(Math.random() * 3)];
      newOdds.match.nextGoal[team] = (
        parseFloat(newOdds.match.nextGoal[team]) + 
        (Math.random() * 0.2 - 0.1)
      ).toFixed(2);
    } else {
      newOdds.match.matchOdds[market] = (
        parseFloat(newOdds.match.matchOdds[market]) + 
        (Math.random() * 0.2 - 0.1)
      ).toFixed(2);
    }
  });

  newOdds.match.timestamp = new Date().toISOString();
  return newOdds;
}

Then simplify your update logic in both files by importing and using this function.

examples/pub-sub-rewind/react/src/app/odds/page.tsx (3)

86-162: Add loading state for initial data fetch.

The component doesn't handle the loading state before receiving the first data, which can result in a poor user experience.

  return (
    <div className="min-h-screen bg-gray-100 p-8">
      <div className="max-w-4xl mx-auto">
+       {!matchData && (
+         <div className="bg-white rounded-lg shadow-lg p-6 mb-8 flex justify-center items-center min-h-[200px]">
+           <div className="text-center">
+             <div className="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite] mr-2"></div>
+             <span>Loading match data...</span>
+           </div>
+         </div>
+       )}
        {matchData && (
          // ... [existing code]
        )}
      </div>
    </div>
  );

96-97: Improve the mobile view with more responsive design techniques.

The current approach for handling responsive design is using simple abbreviations. Consider using a more sophisticated approach.

  <span className="hidden sm:inline">{matchData.match.homeTeam}</span>
- <span className="sm:hidden">
-   {matchData.match.homeTeam.split(' ').map(word => word[0]).join(' ')}
- </span>
+ <span className="sm:hidden">
+   {matchData.match.homeTeam.length > 10 
+     ? `${matchData.match.homeTeam.substring(0, 10)}...` 
+     : matchData.match.homeTeam}
+ </span>

Apply similar changes to the away team abbreviation.

Also applies to: 104-106


70-73: Ensure numeric values are properly validated before arithmetic operations.

There's a potential issue if the parsed odds value is NaN, which would result in invalid calculations.

  if (market === 'nextGoal') {
    const team = Object.keys(newOdds.match.nextGoal)[Math.floor(Math.random() * 3)];
-   newOdds.match.nextGoal[team] = (parseFloat(newOdds.match.nextGoal[team]) + (Math.random() * 0.2 - 0.1)).toFixed(2);
+   const currentOdds = parseFloat(newOdds.match.nextGoal[team]);
+   if (!isNaN(currentOdds)) {
+     newOdds.match.nextGoal[team] = (currentOdds + (Math.random() * 0.2 - 0.1)).toFixed(2);
+   }
  } else {

Apply similar changes to the matchOdds calculation as well.

examples/pub-sub-rewind/javascript/src/script.ts (3)

86-91: Ensure numeric values are properly validated before arithmetic operations.

There's a potential issue if the parsed odds value is NaN, which would result in invalid calculations.

  if (market === 'nextGoal') {
    const team = Object.keys(matchData.match.nextGoal)[Math.floor(Math.random() * 3)];
-   matchData.match.nextGoal[team] = (parseFloat(matchData.match.nextGoal[team]) + (Math.random() * 0.2 - 0.1)).toFixed(2);
+   const currentOdds = parseFloat(matchData.match.nextGoal[team]);
+   if (!isNaN(currentOdds)) {
+     matchData.match.nextGoal[team] = (currentOdds + (Math.random() * 0.2 - 0.1)).toFixed(2);
+   }
  } else {
-   matchData.match.matchOdds[market] = (parseFloat(matchData.match.matchOdds[market]) + (Math.random() * 0.2 - 0.1)).toFixed(2);
+   const currentOdds = parseFloat(matchData.match.matchOdds[market]);
+   if (!isNaN(currentOdds)) {
+     matchData.match.matchOdds[market] = (currentOdds + (Math.random() * 0.2 - 0.1)).toFixed(2);
+   }
  }
🧰 Tools
🪛 ESLint

[error] 88-88: Replace parseFloat(matchData.match.nextGoal[team])·+·(Math.random()·*·0.2·-·0.1) with ⏎··········parseFloat(matchData.match.nextGoal[team])·+⏎··········(Math.random()·*·0.2·-·0.1)⏎········

(prettier/prettier)


[error] 90-90: Replace parseFloat(matchData.match.matchOdds[market])·+·(Math.random()·*·0.2·-·0.1) with ⏎··········parseFloat(matchData.match.matchOdds[market])·+⏎··········(Math.random()·*·0.2·-·0.1)⏎········

(prettier/prettier)


42-47: Verify DOM elements exist before using them.

The code assumes that DOM elements are always found, but this might not be the case if the HTML structure changes.

const preloadButton = document.getElementById('pre-load-odds') as HTMLButtonElement;
+if (!preloadButton) {
+  console.error('Button with id "pre-load-odds" not found');
+}
const urlParams = new URLSearchParams(window.location.search);
const channelName = urlParams.get('name') || 'pub-sub-rewind';
const landingPage = document.getElementById('landing-page');
+if (!landingPage) {
+  console.error('Element with id "landing-page" not found');
+}
const game = document.getElementById('game');
+if (!game) {
+  console.error('Element with id "game" not found');
+}
let channel: Ably.Realtime.Channel | null = null;

184-189: Fix formatting issues according to ESLint.

The static analysis hints indicate formatting issues in the code related to line breaks and indentation.

  marketsToUpdate.forEach((market) => {
    if (market === 'nextGoal') {
      const team = Object.keys(newOdds.match.nextGoal)[Math.floor(Math.random() * 3)];
-     newOdds.match.nextGoal[team] = (parseFloat(newOdds.match.nextGoal[team]) + (Math.random() * 0.2 - 0.1)).toFixed(2);
+     newOdds.match.nextGoal[team] = (
+       parseFloat(newOdds.match.nextGoal[team]) +
+       (Math.random() * 0.2 - 0.1)
+     ).toFixed(2);
    } else {
-     newOdds.match.matchOdds[market] = (parseFloat(newOdds.match.matchOdds[market]) + (Math.random() * 0.2 - 0.1)).toFixed(2);
+     newOdds.match.matchOdds[market] = (
+       parseFloat(newOdds.match.matchOdds[market]) +
+       (Math.random() * 0.2 - 0.1)
+     ).toFixed(2);
    }
  });
🧰 Tools
🪛 ESLint

[error] 186-186: Replace 2 with ⏎··········2,⏎········

(prettier/prettier)


[error] 188-188: Replace parseFloat(newOdds.match.matchOdds[market])·+·(Math.random()·*·0.2·-·0.1) with ⏎··········parseFloat(newOdds.match.matchOdds[market])·+⏎··········(Math.random()·*·0.2·-·0.1)⏎········

(prettier/prettier)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b3cc664 and 64d642c.

⛔ Files ignored due to path filters (2)
  • examples/pub-sub-rewind/javascript/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
  • examples/pub-sub-rewind/react/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (25)
  • examples/pub-sub-rewind/javascript/.env.example (1 hunks)
  • examples/pub-sub-rewind/javascript/.gitignore (1 hunks)
  • examples/pub-sub-rewind/javascript/README.md (1 hunks)
  • examples/pub-sub-rewind/javascript/index.html (1 hunks)
  • examples/pub-sub-rewind/javascript/package.json (1 hunks)
  • examples/pub-sub-rewind/javascript/src/script.ts (1 hunks)
  • examples/pub-sub-rewind/javascript/src/styles.css (1 hunks)
  • examples/pub-sub-rewind/javascript/tailwind.config.js (1 hunks)
  • examples/pub-sub-rewind/javascript/tsconfig.json (1 hunks)
  • examples/pub-sub-rewind/javascript/vite-env.d.ts (1 hunks)
  • examples/pub-sub-rewind/javascript/vite.config.ts (1 hunks)
  • examples/pub-sub-rewind/page.md (1 hunks)
  • examples/pub-sub-rewind/react/.env.example (1 hunks)
  • examples/pub-sub-rewind/react/.eslintrc.json (1 hunks)
  • examples/pub-sub-rewind/react/.gitignore (1 hunks)
  • examples/pub-sub-rewind/react/README.md (1 hunks)
  • examples/pub-sub-rewind/react/next.config.ts (1 hunks)
  • examples/pub-sub-rewind/react/package.json (1 hunks)
  • examples/pub-sub-rewind/react/postcss.config.mjs (1 hunks)
  • examples/pub-sub-rewind/react/src/app/layout.tsx (1 hunks)
  • examples/pub-sub-rewind/react/src/app/odds/page.tsx (1 hunks)
  • examples/pub-sub-rewind/react/src/app/page.tsx (1 hunks)
  • examples/pub-sub-rewind/react/styles/styles.css (1 hunks)
  • examples/pub-sub-rewind/react/tailwind.config.ts (1 hunks)
  • examples/pub-sub-rewind/react/tsconfig.json (1 hunks)
🧰 Additional context used
🪛 ESLint
examples/pub-sub-rewind/javascript/vite.config.ts

[error] 1-1: Insert ;

(prettier/prettier)


[error] 6-9: Replace ⏎········require('tailwindcss'),⏎········require('autoprefixer'),⏎······ with require('tailwindcss'),·require('autoprefixer')

(prettier/prettier)


[error] 10-10: Insert ,

(prettier/prettier)


[error] 11-11: Insert ,

(prettier/prettier)


[error] 12-12: Insert ;⏎

(prettier/prettier)

examples/pub-sub-rewind/javascript/tailwind.config.js

[error] 3-6: Replace ⏎····"./index.html",⏎····"./src/**/*.{js,jsx,ts,tsx}",⏎·· with './index.html',·'./src/**/*.{js,jsx,ts,tsx}'

(prettier/prettier)


[error] 11-12: Replace with ;

(prettier/prettier)

examples/pub-sub-rewind/javascript/src/script.ts

[error] 88-88: Replace parseFloat(matchData.match.nextGoal[team])·+·(Math.random()·*·0.2·-·0.1) with ⏎··········parseFloat(matchData.match.nextGoal[team])·+⏎··········(Math.random()·*·0.2·-·0.1)⏎········

(prettier/prettier)


[error] 90-90: Replace parseFloat(matchData.match.matchOdds[market])·+·(Math.random()·*·0.2·-·0.1) with ⏎··········parseFloat(matchData.match.matchOdds[market])·+⏎··········(Math.random()·*·0.2·-·0.1)⏎········

(prettier/prettier)


[error] 186-186: Replace 2 with ⏎··········2,⏎········

(prettier/prettier)


[error] 188-188: Replace parseFloat(newOdds.match.matchOdds[market])·+·(Math.random()·*·0.2·-·0.1) with ⏎··········parseFloat(newOdds.match.matchOdds[market])·+⏎··········(Math.random()·*·0.2·-·0.1)⏎········

(prettier/prettier)

🪛 LanguageTool
examples/pub-sub-rewind/javascript/README.md

[uncategorized] ~25-~25: Possible missing comma found.
Context: ...mple .env.local ``` 4. In .env.local update the value of `VITE_PUBLIC_ABLY_KEY` to ...

(AI_HYDRA_LEO_MISSING_COMMA)


[style] ~25-~25: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...ue of VITE_PUBLIC_ABLY_KEY to be your Ably API key. 5. Install dependencies: ```...

(ADVERB_REPETITION_PREMIUM)

examples/pub-sub-rewind/react/README.md

[style] ~25-~25: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...ue of NEXT_PUBLIC_ABLY_KEY to be your Ably API key. 5. Install dependencies: ```...

(ADVERB_REPETITION_PREMIUM)

examples/pub-sub-rewind/page.md

[uncategorized] ~5-~5: Possible missing article found.
Context: ... start working in your application with context of what happened before they went joine...

(AI_HYDRA_LEO_MISSING_THE)


[uncategorized] ~17-~17: Loose punctuation mark.
Context: ...ocs/getting-started/react#ably-provider): initializes and manages a shared pub/su...

(UNLIKELY_OPENING_PUNCTUATION)


[uncategorized] ~18-~18: Loose punctuation mark.
Context: .../getting-started/react#channel-provider): manages the state and functionality of ...

(UNLIKELY_OPENING_PUNCTUATION)


[style] ~114-~114: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...T_PUBLIC_ABLY_KEY` variable to use your Ably API key. // Javascript In CodeSandbox...

(ADVERB_REPETITION_PREMIUM)


[style] ~118-~118: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...E_PUBLIC_ABLY_KEY` variable to use your Ably API key.

(ADVERB_REPETITION_PREMIUM)

🔇 Additional comments (21)
examples/pub-sub-rewind/javascript/vite-env.d.ts (2)

1-4: Well-defined environment variable interface

The ImportMetaEnv interface properly declares the Ably API key as a readonly string property, preventing accidental modifications. The helpful comment on line 3 encourages future developers to extend this interface as needed.


6-8: Correctly extends ImportMeta interface

This properly extends the Vite's built-in ImportMeta interface to include the environment variables, ensuring type safety when accessing import.meta.env.VITE_PUBLIC_ABLY_KEY throughout the application.

examples/pub-sub-rewind/react/styles/styles.css (1)

1-3: Standard Tailwind CSS setup

The file correctly includes the three essential Tailwind directives to properly incorporate base styles, component styles, and utility classes into the project.

examples/pub-sub-rewind/react/postcss.config.mjs (1)

1-9: Solid PostCSS Config Setup

The PostCSS configuration is set up correctly using an inline TypeScript hint, which increases type safety and integration with tools that support type checking. No issues were found.

examples/pub-sub-rewind/react/.eslintrc.json (1)

1-4: Clean ESLint Configuration

This file correctly extends Next.js's core web vitals and TypeScript rules, ensuring adherence to best practices for Next.js apps. Everything looks properly configured.

examples/pub-sub-rewind/javascript/src/styles.css (1)

1-24: Effective Use of Tailwind Directives and Custom Styles

The CSS file appropriately imports Tailwind’s base, components, and utilities, with additional custom flexbox-based rules for centering elements and styling input fields. The styling is concise and meets the demo requirements.

examples/pub-sub-rewind/javascript/README.md (3)

1-4: Well-structured introduction to the example.

The introduction clearly explains the purpose of this example, introducing Ably Pub/Sub and the rewind feature.


5-38: Clear setup instructions with logical flow.

The step-by-step instructions are comprehensive and easy to follow, covering all the necessary steps from cloning to running the application.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~25-~25: Possible missing comma found.
Context: ...mple .env.local ``` 4. In .env.local update the value of `VITE_PUBLIC_ABLY_KEY` to ...

(AI_HYDRA_LEO_MISSING_COMMA)


[style] ~25-~25: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...ue of VITE_PUBLIC_ABLY_KEY to be your Ably API key. 5. Install dependencies: ```...

(ADVERB_REPETITION_PREMIUM)


16-17:

✅ Verification successful

Verify the directory path is correct

The path appears to start with a leading slash, which might cause confusion as it suggests starting from the root directory rather than from the cloned repository root.

-cd /examples/pub-sub-rewind/javascript/
+cd examples/pub-sub-rewind/javascript/

🏁 Script executed:

#!/bin/bash
# Check if the directory structure exists as specified in the README
if [ -d "examples/pub-sub-rewind/javascript/" ]; then
  echo "✅ Directory path exists as specified in the README (without leading slash)"
  exit 0
elif [ -d "/examples/pub-sub-rewind/javascript/" ]; then
  echo "❌ Directory path exists with leading slash - README should be updated"
  exit 1
else
  echo "❌ Directory path does not exist in either format"
  exit 1
fi

Length of output: 216


Ensure README Uses a Relative Directory Path

The verification shows that the directory exists only when using the relative path. Please update the command on lines 16-17 from using a leading slash to the relative path:

  • File: examples/pub-sub-rewind/javascript/README.md (Lines 16-17)
  • Diff:
    -cd /examples/pub-sub-rewind/javascript/
    +cd examples/pub-sub-rewind/javascript/
examples/pub-sub-rewind/javascript/.gitignore (1)

1-36: Comprehensive .gitignore with appropriate patterns.

This .gitignore file is well-structured and includes all necessary patterns for a JavaScript/TypeScript project, ensuring that temporary files, build artifacts, dependencies, and sensitive information aren't committed to the repository.

examples/pub-sub-rewind/react/src/app/layout.tsx (2)

1-20: Correct implementation of Next.js layout component.

The RootLayout component correctly follows Next.js app router conventions and provides a clean base structure for the application.


4-4:

✅ Verification successful

Ensure the CSS file path is correct.

Verify that the relative import path to the styles file is correct. Make sure the directory structure matches your import statement.


🏁 Script executed:

#!/bin/bash
# Check if the CSS file exists at the specified path
if [ -f "examples/pub-sub-rewind/react/styles/styles.css" ]; then
  echo "✅ CSS file exists at the expected path"
  exit 0
else
  echo "❌ CSS file not found at the expected path"
  # Try to find where it might be located
  echo "Searching for styles.css in the react directory..."
  find examples/pub-sub-rewind/react -name "styles.css" -type f
  exit 1
fi

Length of output: 156


CSS Import Path Verified as Correct

The verification confirmed that the CSS file exists at the expected path (examples/pub-sub-rewind/react/styles/styles.css), which validates the relative import (../../styles/styles.css) in examples/pub-sub-rewind/react/src/app/layout.tsx. No changes are necessary.

examples/pub-sub-rewind/react/.gitignore (1)

1-40: Well-structured .gitignore file.

This is a comprehensive .gitignore file following best practices for a Next.js/React project. It properly excludes:

  • Dependencies and package management files with appropriate Yarn 2+ exceptions
  • Build and testing artifacts
  • Environment files
  • System files and logs
  • TypeScript generated files

The structure with clear section comments makes maintenance easier for future contributors.

examples/pub-sub-rewind/javascript/tsconfig.json (2)

2-12: TypeScript configuration looks appropriate for a browser application.

The compiler options are well-configured for a modern browser application with proper type checking enabled. Setting noImplicitAny to true helps enforce type safety.


13-15: Properly structured include/exclude patterns.

The configuration correctly includes TypeScript files from the source directory while excluding appropriate directories like node_modules, dist, and lib.

examples/pub-sub-rewind/react/tailwind.config.ts (1)

1-18: Well-typed Tailwind configuration with proper CSS variable usage.

This configuration is well-structured and follows Tailwind CSS best practices:

  • Uses TypeScript's satisfies Config for type checking
  • Correctly specifies content paths for all relevant file types
  • Uses CSS variables for theme colors, enabling easier theme switching

Good job implementing a type-safe configuration.

examples/pub-sub-rewind/react/README.md (1)

1-40: Clear and comprehensive README with good setup instructions.

The README provides a concise description of the example and clear step-by-step instructions for setting up and running the application.

🧰 Tools
🪛 LanguageTool

[style] ~25-~25: This adverb was used twice in the sentence. Consider removing one of them or replacing them with a synonym.
Context: ...ue of NEXT_PUBLIC_ABLY_KEY to be your Ably API key. 5. Install dependencies: ```...

(ADVERB_REPETITION_PREMIUM)

examples/pub-sub-rewind/react/tsconfig.json (1)

1-28: TypeScript Configuration is Well-Structured
The new configuration includes all the essential compiler options for modern React and Next.js development. The settings for strict type-checking, incremental builds, and module resolution are appropriate.

examples/pub-sub-rewind/javascript/package.json (1)

1-25: Package.json for JavaScript Example is Set Up Correctly
The dependencies, devDependencies, and scripts are appropriately defined for a Vite-based project. Ensure that the version constraints (especially for critical libraries like Ably and Vite) are maintained as per project requirements.

examples/pub-sub-rewind/react/package.json (1)

1-29: Next.js Package Configuration is Solid
The package.json for the React example is well configured with clear scripts and dependency versioning that support Next.js, React, and Tailwind CSS development. Ensure that the version numbers align with your project’s long-term stability plans.

examples/pub-sub-rewind/react/src/app/odds/page.tsx (1)

37-37:

❓ Verification inconclusive

Use consistent channel options with rewind parameter.

The rewind: '10' parameter requests the last 10 messages from the channel history. Ensure this value is consistent with your application requirements and message volume expectations.


🌐 Web query:

What is the recommended rewind parameter value for Ably pub/sub channels?

Error during web search


Action: Verify the Ably rewind parameter value for consistency

The current implementation uses rewind: '10' to retrieve the last 10 messages from the channel history. However, we encountered an error when attempting to confirm the recommended value for Ably pub/sub channels. Please double-check the Ably documentation (or any internal guidelines you might have) to ensure that this value aligns with both your application requirements and the message volume expectations. If necessary, update all instances where the rewind parameter is configured to maintain consistency.

@ably ably deleted a comment from coderabbitai bot Mar 5, 2025
@ably ably deleted a comment from coderabbitai bot Mar 5, 2025
@ably ably deleted a comment from coderabbitai bot Mar 5, 2025
@ably ably deleted a comment from coderabbitai bot Mar 5, 2025
@ably ably deleted a comment from coderabbitai bot Mar 5, 2025
@ably ably deleted a comment from coderabbitai bot Mar 5, 2025
@ably ably deleted a comment from coderabbitai bot Mar 5, 2025
@GregHolmes GregHolmes force-pushed the EDU-1691-Example-Pub-Sub-History-Rewind branch from cea485a to af74646 Compare March 5, 2025 14:12
@GregHolmes GregHolmes force-pushed the EDU-1691-Example-Pub-Sub-History-Rewind branch 3 times, most recently from 16f6c3c to edf3110 Compare March 19, 2025 10:45
@GregHolmes GregHolmes force-pushed the EDU-1691-Example-Pub-Sub-History-Rewind branch from 5a1d7c7 to bb55a2d Compare March 19, 2025 11:03
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