Skip to content

[Components] bluesky - new components #15087

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 31, 2024
Merged

Conversation

jcortes
Copy link
Collaborator

@jcortes jcortes commented Dec 27, 2024

WHY

Resolves #15066

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced modules for creating posts, liking posts, and retrieving threads on the Bluesky platform.
    • Added functionality for monitoring new followers and tracking new posts by specific authors.
    • Implemented polling capabilities for managing resource updates.
    • Added support for handling new timeline posts.
  • Enhancements

    • Expanded application properties and methods for improved API interactions and resource management.
    • Introduced new constants and utility functions to facilitate various operations.
  • Version Update

    • Updated package version from 0.0.1 to 0.1.0 and added new dependencies.

@jcortes jcortes added action New Action Request trigger / source New trigger / source request labels Dec 27, 2024
@jcortes jcortes self-assigned this Dec 27, 2024
Copy link

vercel bot commented Dec 27, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

3 Skipped Deployments
Name Status Preview Comments Updated (UTC)
docs-v2 ⬜️ Ignored (Inspect) Visit Preview Dec 31, 2024 8:06pm
pipedream-docs ⬜️ Ignored (Inspect) Dec 31, 2024 8:06pm
pipedream-docs-redirect-do-not-edit ⬜️ Ignored (Inspect) Dec 31, 2024 8:06pm

Copy link
Contributor

coderabbitai bot commented Dec 27, 2024

Walkthrough

This pull request introduces a comprehensive integration for the Bluesky platform, adding multiple components for interacting with its social media features. It includes new modules for creating posts, liking posts, and retrieving threads, alongside polling sources for tracking new posts and followers. Enhancements to utility functions and constants support these features, all aligned with the Bluesky API documentation to facilitate robust social media interactions.

Changes

File Change Summary
components/bluesky/actions/create-post/create-post.mjs New module for creating posts on Bluesky
components/bluesky/actions/like-post/like-post.mjs New module for liking posts on Bluesky
components/bluesky/actions/retrieve-thread/retrieve-thread.mjs New module for retrieving post threads
components/bluesky/bluesky.app.mjs Extensive updates with new methods for API interactions and expanded prop definitions
components/bluesky/common/constants.mjs Added constants for API interactions and resource types
components/bluesky/common/utils.mjs Added utility functions for iteration and property access
components/bluesky/sources/new-follower-on-account/new-follower-on-account.mjs New module for tracking new followers on an account
components/bluesky/sources/new-posts-by-author/new-posts-by-author.mjs New module for tracking new posts by a specific author
components/bluesky/sources/new-timeline-posts/new-timeline-posts.mjs New module for handling new timeline posts
components/bluesky/sources/*/test-event.mjs New test event modules for simulating user interactions

Assessment against linked issues

Objective Addressed Explanation
New posts by author polling source [#15066]
New follower on account polling source [#15066]
New timeline posts polling source [#15066]
Create post action [#15066]
Retrieve thread action [#15066]
Like post action [#15066]

Possibly related PRs

  • New Components - boldsign #15013: Introduces new components related to the BoldSign service, which may involve similar functionalities for document management as the main PR's post creation module.
  • New Components - lusha #14994: Adds new components for the Lusha service, which includes actions for enriching company and contact information, potentially related to the main PR's focus on creating posts.
  • New Components - contentstack #15037: Introduces new components for Contentstack, which includes actions for managing content entries, possibly related to the main PR's functionality of creating posts.
  • OpenAI - Migrate from Assistant API v1 to v2 #15061: Updates the OpenAI components to migrate to a new API version, which may involve changes in how actions are defined and executed, potentially relevant to the main PR's structure for creating posts.

Suggested reviewers

  • michelle0927

Poem

🐰 Bluesky's wings, a digital delight,
Coding rabbit hops with all his might,
Posts and likes, threads unfurled,
A social media adventure, code-controlled world!
Hop, hop, hooray for tech's bright flight! 🚀


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 generate docstrings to generate docstrings for this PR. (Beta)
  • @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.

@jcortes jcortes force-pushed the bluesky-new-components branch from 96e6266 to 56bb358 Compare December 27, 2024 21:38
Copy link
Contributor

@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: 1

🧹 Nitpick comments (21)
components/bluesky/bluesky.app.mjs (7)

8-24: Consider adding input validation
The prop definitions for postUrl, authorId, and accountId look good, but you might want to perform extra validation (e.g., ensure the string is non-empty, follows an expected format/regex) to help users catch misconfigurations early.


26-40: Consider adding more descriptive errors
This helper correctly throws an error if the URL format doesn't match. It's good practice to include more detail in the error message (e.g., which part failed, or an example of the expected format) to help with debugging.


47-55: Potential token refresh logic
If tokens can expire, consider adding a refresh mechanism in getHeaders(). Currently, it returns the same bearer token without renewing or checking validity.


56-64: Enhance request error handling
Consider wrapping _makeRequest in a try/catch block or providing a custom error handler to better handle unexpected network or API errors, especially if you need to differentiate or retry certain failures.


65-70: Clarify naming of “post” method
Naming this method post can be slightly ambiguous since “post” might also refer to a resource. Consider postData or postRequest for added clarity.


93-110: Duplicate patterns across feed/timeline/followers
getAuthorFeed, getTimeline, and getFollowers methods are nearly identical aside from the path. Consider consolidating them into a single method that accepts the path as a parameter, reducing repetitive code.


111-169: Watch for date/time comparisons and large loops
The generator logic here is robust, but take care with date comparisons if timezones or partial date strings appear. Also consider upper bounds or concurrency controls if there’s a risk of high-volume data, which could lead to a slow or memory-intensive process.

components/bluesky/sources/new-timeline-posts/new-timeline-posts.mjs (1)

4-38: Source logic aligns with polling structure
This source extends common effectively, implementing getDateField, getResourceName, and getResourcesFnArgs. You might consider optional parameters (like filtering or pagination settings) for advanced usage.

components/bluesky/actions/create-post/create-post.mjs (1)

4-39: Consider validation or text limits
Providing a text field is simple and intuitive. You might want to block extremely large posts or empty text if the API has constraints, and handle errors gracefully.

components/bluesky/sources/new-follower-on-account/new-follower-on-account.mjs (1)

4-49: Check property availability
The logic relies on resource.createdAt. If the API changes or the follower object lacks that field, date parsing may fail. Consider a fallback or error check.

components/bluesky/sources/new-posts-by-author/new-posts-by-author.mjs (5)

4-11: Ensure testing coverage and naming consistency for the source.
This newly introduced source extends behaviors from common. Make sure you have tests that validate both the inherited logic and the unique features (e.g., deduplication, author ID usage) in this file.


21-22: Confirm no override conflicts with merged methods.
By spreading common.methods, we rely on no collisions between method names. Confirm that no method in this file conflicts with methods from common.


26-28: Resource naming clarity.
Returning "feed" as the resource name might cause confusion if multiple feed types are introduced in the future. If relevant, consider a more descriptive resource name or confirm that “feed” is unambiguous for now.


32-39: Consider removing debug: true for production.
Debug logs might reveal sensitive information. If the debug flag is more for development, consider removing or parameterizing it for different environments.


49-50: Optional: Remove or replace sample event emitter in production.
If sampleEmit is purely for testing or documentation, consider removing or flagging it as non-production. It could clutter logs or confuse future maintainers.

components/bluesky/common/constants.mjs (1)

26-30: Confirm appropriate defaults.
DEFAULT_LIMIT = 3 and DEFAULT_MAX = 600 may affect performance or user experiences if the feed is large. Confirm these values suit typical usage patterns.

components/bluesky/actions/like-post/like-post.mjs (2)

19-29: Destructuring usage is clear.
The destructuring for app and postUrl is neat. Ensure that usage of this remains consistent—mixing direct destructuring with this references can be confused if used differently elsewhere.


58-60: Export summary.
This line provides a nice summary to confirm success. Consider including the postId or handle in the message for traceability, if relevant.

components/bluesky/actions/retrieve-thread/retrieve-thread.mjs (2)

54-59: Error handling for unknown handles.
If resolveHandle can fail, does the code handle or re-throw? Clarify whether the user sees a useful error message if the handle cannot be resolved.


70-72: Export summary.
Returning a success message is helpful. Optionally, logging the length of retrieved posts or thread data might provide more context.

components/bluesky/sources/common/polling.mjs (1)

22-26: Initialize state during deployment
Using this.setIsFirstRun(true) in the deploy hook is a good approach for ensuring any initial run logic is consistently triggered. However, consider logging or documenting that this is the first execution for debugging or observability.

🛑 Comments failed to post (1)
components/bluesky/common/constants.mjs (1)

4-17: ⚠️ Potential issue

Typo in REQUES_TLESS.
The key REQUES_TLESS seems incorrect. The intended key might be REQUEST_LESS. Fixing it will avoid confusion when referencing this event constant in other parts of the code.

-  REQUES_TLESS: "app.bsky.feed.defs#requestLess",
+  REQUEST_LESS: "app.bsky.feed.defs#requestLess",
📝 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 INTERACTION_EVENT = {
  REQUEST_LESS: "app.bsky.feed.defs#requestLess",
  REQUEST_MORE: "app.bsky.feed.defs#requestMore",
  CLICK_THROUGH_ITEM: "app.bsky.feed.defs#clickthroughItem",
  CLICK_THROUGH_AUTHOR: "app.bsky.feed.defs#clickthroughAuthor",
  CLICK_THROUGH_REPOSTER: "app.bsky.feed.defs#clickthroughReposter",
  CLICK_THROUGH_EMBED: "app.bsky.feed.defs#clickthroughEmbed",
  INTERACTION_SEEN: "app.bsky.feed.defs#interactionSeen",
  INTERACTION_LIKE: "app.bsky.feed.defs#interactionLike",
  INTERACTION_REPOST: "app.bsky.feed.defs#interactionRepost",
  INTERACTION_REPLY: "app.bsky.feed.defs#interactionReply",
  INTERACTION_QUOTE: "app.bsky.feed.defs#interactionQuote",
  INTERACTION_SHARE: "app.bsky.feed.defs#interactionShare",
};

Copy link
Contributor

@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

🧹 Nitpick comments (5)
components/bluesky/common/constants.mjs (1)

26-29: Consider documenting the significance of default values.

The default values for limits and flags would benefit from JSDoc comments explaining their purpose and impact.

+ /** Maximum number of items to fetch per request */
  const DEFAULT_LIMIT = 3;
+ /** Maximum total items to process */
  const DEFAULT_MAX = 600;
+ /** Key for tracking first run state */
  const IS_FIRST_RUN = "isFirstRun";
+ /** Key for tracking last processed date */
  const LAST_DATE_AT = "lastDateAt";
components/bluesky/bluesky.app.mjs (2)

26-40: Enhance error message for invalid URLs.

While the URL parsing logic is solid, the error message could be more helpful by including the expected format.

-      if (!match) {
-        throw new Error("Invalid post URL");
+      if (!match) {
+        throw new Error("Invalid post URL. Expected format: https://bsky.app/profile/handle.bsky.social/post/postId");

111-169: Consider using a proper logger and simplifying control flow.

While the pagination logic is thorough, consider these improvements:

  1. Replace console.log with a proper logger for better observability
  2. Simplify nested conditions for better readability
-          if (!isLastDateGreater) {
-            yield resource;
-            resourcesCount += 1;
-          }
-
-          if (resourcesCount >= max) {
+          if (isLastDateGreater) {
+            continue;
+          }
+          
+          yield resource;
+          resourcesCount += 1;
+          
+          if (resourcesCount >= max) {

Consider introducing a logger utility that can be configured based on the environment:

// common/logger.mjs
export default {
  log: (message) => {
    if (process.env.NODE_ENV !== 'production') {
      console.log(`[Bluesky] ${message}`);
    }
  }
};
components/bluesky/actions/retrieve-thread/retrieve-thread.mjs (1)

40-72: Consider adding response validation.

While the implementation is solid, consider validating the response before returning it to ensure it contains the expected thread data.

     const response = await getPostThread({
       $,
       params: {
         uri: app.getPostUri(postId, did),
         depth,
         parentHeight,
       },
     });
 
+    if (!response?.thread) {
+      throw new Error('Failed to retrieve thread data');
+    }
+
     $.export("$summary", "Successfully retrieved thread.");
     return response;
components/bluesky/sources/new-timeline-posts/test-event.mjs (1)

1-137: Maintain consistency in mock identifier patterns.

While the mock data is comprehensive, the mock identifiers could follow a more consistent pattern. For example:

  • Some use descriptive prefixes: mockParentDid, mockRootDid
  • Others are generic: mockId, mockCid

Consider using consistent naming patterns for all mock identifiers. For example:

-        "following": "at://did:plc:mockFollow/app.bsky.graph.follow/mockId"
+        "following": "at://did:plc:mockFollowDid/app.bsky.graph.follow/mockFollowId"

The overall structure and completeness of the mock data is excellent for testing purposes.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 96e6266 and 56bb358.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • components/bluesky/actions/create-post/create-post.mjs (1 hunks)
  • components/bluesky/actions/like-post/like-post.mjs (1 hunks)
  • components/bluesky/actions/retrieve-thread/retrieve-thread.mjs (1 hunks)
  • components/bluesky/bluesky.app.mjs (1 hunks)
  • components/bluesky/common/constants.mjs (1 hunks)
  • components/bluesky/common/utils.mjs (1 hunks)
  • components/bluesky/package.json (2 hunks)
  • components/bluesky/sources/common/polling.mjs (1 hunks)
  • components/bluesky/sources/new-follower-on-account/new-follower-on-account.mjs (1 hunks)
  • components/bluesky/sources/new-follower-on-account/test-event.mjs (1 hunks)
  • components/bluesky/sources/new-posts-by-author/new-posts-by-author.mjs (1 hunks)
  • components/bluesky/sources/new-posts-by-author/test-event.mjs (1 hunks)
  • components/bluesky/sources/new-timeline-posts/new-timeline-posts.mjs (1 hunks)
  • components/bluesky/sources/new-timeline-posts/test-event.mjs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • components/bluesky/sources/new-follower-on-account/test-event.mjs
  • components/bluesky/actions/create-post/create-post.mjs
  • components/bluesky/common/utils.mjs
  • components/bluesky/sources/new-posts-by-author/test-event.mjs
  • components/bluesky/actions/like-post/like-post.mjs
  • components/bluesky/sources/new-timeline-posts/new-timeline-posts.mjs
  • components/bluesky/sources/common/polling.mjs
  • components/bluesky/sources/new-posts-by-author/new-posts-by-author.mjs
🔇 Additional comments (11)
components/bluesky/package.json (1)

3-3: LGTM! Version bump and dependency addition look appropriate.

The version bump to 0.1.0 aligns with the addition of new Bluesky components. The @pipedream/platform dependency is required for Pipedream component functionality.

Also applies to: 15-17

components/bluesky/sources/new-follower-on-account/new-follower-on-account.mjs (3)

6-11: LGTM! Component metadata is well-defined.

The component has clear name, description (with API docs link), and appropriate version starting at 0.0.1. The deduplication setting ensures unique events.


12-20: LGTM! Props extension is clean and minimal.

Properly extends common props and adds the required accountId prop using the app's propDefinition.


40-46: LGTM! Meta generation is well-structured.

The generateMeta method creates a clear event structure with unique ID, descriptive summary, and properly parsed timestamp.

components/bluesky/common/constants.mjs (1)

24-24: LGTM! Regex pattern for URL parsing is well-defined.

The regex properly captures handle and postId from Bluesky post URLs using named groups.

components/bluesky/bluesky.app.mjs (4)

8-24: LGTM! Well-structured prop definitions with clear descriptions.

The prop definitions are well-documented and include helpful examples. The URL format specification in the description will help users provide correct input.


41-55: LGTM! Well-structured utility methods with proper authentication.

The methods follow single responsibility principle and properly handle authentication headers.


56-110: LGTM! Well-organized HTTP request methods with consistent patterns.

The request methods are well-structured, modular, and follow a consistent pattern. Good use of default parameters and proper request configuration.


170-171: LGTM! Clean pagination wrapper.

The paginate method provides a clean interface to the iteration functionality.

components/bluesky/actions/retrieve-thread/retrieve-thread.mjs (2)

3-31: LGTM! Well-documented component with proper validation.

The component metadata is well-structured with appropriate validation for depth and parentHeight parameters.


32-39: LGTM! Clean method implementation.

The getPostThread method follows the established pattern and properly delegates to the app's request method.

Copy link
Collaborator

@michelle0927 michelle0927 left a comment

Choose a reason for hiding this comment

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

Looks good, just a few stray debug: true.

},
getResourcesFnArgs() {
return {
debug: true,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
debug: true,

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

These are on purpose!

},
getResourcesFnArgs() {
return {
debug: true,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
debug: true,

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

These are on purpose!

},
getResourcesFnArgs() {
return {
debug: true,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
debug: true,

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

These are on purpose only for sources!

Copy link
Contributor

@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

🧹 Nitpick comments (9)
components/bluesky/sources/new-posts-by-author/new-posts-by-author.mjs (1)

40-47: Consider destructuring optimization.

The current destructuring pattern can be simplified to improve readability.

-    const {
-      app,
-      getPostThread,
-      postUrl,
-      depth,
-      parentHeight,
-    } = this;
+    const { app, getPostThread, postUrl, depth, parentHeight } = this;
components/bluesky/actions/retrieve-thread/retrieve-thread.mjs (2)

17-23: Add minimum value validation for depth and parentHeight.

While maximum values are properly set to 100, there's no minimum value validation. Consider adding min: 0 to prevent negative values.

    depth: {
      type: "integer",
      label: "Depth",
      description: "How many levels of reply depth should be included in response. Default is `6`.",
      optional: true,
      max: 100,
+     min: 0,
    },
    parentHeight: {
      type: "integer",
      label: "Parent Height",
      description: "How many levels of parent (and grandparent, etc) post to include. Default is `80`.",
      optional: true,
      max: 100,
+     min: 0,
    },

Also applies to: 24-30


70-71: Enhance the success message with thread details.

The success message could be more informative by including basic thread information.

-    $.export("$summary", "Successfully retrieved thread.");
+    $.export("$summary", `Successfully retrieved thread with ${response.thread?.replyCount || 0} replies.`);
components/bluesky/sources/new-posts-by-author/test-event.mjs (2)

16-16: Use relative dates for test data.

The hardcoded future dates (2025) might cause tests to behave differently over time. Consider using relative dates.

-      createdAt: "2025-01-01T08:00:00.000Z",
+      createdAt: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(), // 1 day ago

Also applies to: 20-20, 62-62, 65-65, 94-94, 98-98


3-4: Use consistent mock IDs across test data.

The mock IDs (mockPostId, mockRootPost, mockParentPost) should follow a consistent naming pattern for better readability and maintainability.

-    uri: "at://did:plc:fakeOne/app.bsky.feed.post/mockPostId",
-    cid: "bafyreimachangedxxxyyyzzz",
+    uri: "at://did:plc:fakeOne/app.bsky.feed.post/mock-post-1",
+    cid: "bafyreim-mock-cid-1",

Also applies to: 48-49, 82-83

components/bluesky/bluesky.app.mjs (4)

9-23: Consider adding pattern validation for postUrl prop.

While the URL validation is handled in getHandleAndPostIdFromUrl, adding pattern validation directly in the prop definition would provide immediate feedback to users.

 postUrl: {
   type: "string",
   label: "Post URL",
   description: "The URL will look like `https://bsky.app/profile/myhandle.bsky.social/post/3le7x3qgmaw23`.",
+  pattern: "^https://bsky\\.app/profile/[\\w.-]+/post/[\\w]+$",
 },

26-40: Enhance error message for invalid post URL.

The error handling is good, but the error message could be more helpful by including the expected URL format.

-        throw new Error("Invalid post URL");
+        throw new Error("Invalid post URL. Expected format: https://bsky.app/profile/handle.bsky.social/post/postId");

56-80: Add error handling wrapper for HTTP requests.

While using axios handles basic HTTP errors, consider adding custom error handling to provide more context-specific error messages.

 _makeRequest({
   $ = this, path, headers, ...args
 } = {}) {
+  try {
     return axios($, {
       ...args,
       url: this.getUrl(path),
       headers: this.getHeaders(headers),
     });
+  } catch (error) {
+    const statusCode = error.response?.status;
+    const message = error.response?.data?.message || error.message;
+    throw new Error(`Bluesky API error (${statusCode}): ${message}`);
+  }
 },

81-110: Add JSDoc documentation for API methods.

Adding JSDoc will improve code maintainability and provide better IDE support.

Example for one method:

+/**
+ * Retrieves a record from the Bluesky API
+ * @param {Object} args - Request arguments
+ * @param {Object} [args.params] - Query parameters
+ * @param {string} [args.params.repo] - The repository DID
+ * @param {string} [args.params.collection] - The record collection
+ * @param {string} [args.params.rkey] - The record key
+ * @returns {Promise<Object>} The record data
+ */
 getRecord(args = {}) {
   return this._makeRequest({
     path: "/com.atproto.repo.getRecord",
     ...args,
   });
 },
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 56bb358 and 3a96ff7.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • components/bluesky/actions/create-post/create-post.mjs (1 hunks)
  • components/bluesky/actions/like-post/like-post.mjs (1 hunks)
  • components/bluesky/actions/retrieve-thread/retrieve-thread.mjs (1 hunks)
  • components/bluesky/bluesky.app.mjs (1 hunks)
  • components/bluesky/common/constants.mjs (1 hunks)
  • components/bluesky/common/utils.mjs (1 hunks)
  • components/bluesky/package.json (2 hunks)
  • components/bluesky/sources/common/polling.mjs (1 hunks)
  • components/bluesky/sources/new-follower-on-account/new-follower-on-account.mjs (1 hunks)
  • components/bluesky/sources/new-follower-on-account/test-event.mjs (1 hunks)
  • components/bluesky/sources/new-posts-by-author/new-posts-by-author.mjs (1 hunks)
  • components/bluesky/sources/new-posts-by-author/test-event.mjs (1 hunks)
  • components/bluesky/sources/new-timeline-posts/new-timeline-posts.mjs (1 hunks)
  • components/bluesky/sources/new-timeline-posts/test-event.mjs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (10)
  • components/bluesky/package.json
  • components/bluesky/common/utils.mjs
  • components/bluesky/actions/create-post/create-post.mjs
  • components/bluesky/sources/new-timeline-posts/new-timeline-posts.mjs
  • components/bluesky/sources/new-follower-on-account/test-event.mjs
  • components/bluesky/sources/new-timeline-posts/test-event.mjs
  • components/bluesky/actions/like-post/like-post.mjs
  • components/bluesky/sources/new-follower-on-account/new-follower-on-account.mjs
  • components/bluesky/sources/common/polling.mjs
  • components/bluesky/common/constants.mjs
🔇 Additional comments (5)
components/bluesky/sources/new-posts-by-author/new-posts-by-author.mjs (2)

1-11: LGTM! Component metadata is well-defined.

The component is properly structured with clear key, name, description, and version. The description includes a helpful link to the API documentation.


34-34: Debug flag should be disabled in production.

The debug: true flag is set in getResourcesFnArgs(). While this was marked as intentional in a previous review, it's recommended to make this configurable or disabled by default in production.

components/bluesky/sources/new-posts-by-author/test-event.mjs (1)

1-137: Verify test data structure against API schema.

The mock data structure should be verified against the Bluesky API schema to ensure it matches the expected format.

✅ Verification successful

Let's analyze the codebase for Bluesky API related patterns and type definitions to verify the test data structure.


Let's analyze the test files and look for any type definitions or schemas in the Bluesky component to verify the consistency of the test data structure.


Let's examine these core files to find any schema definitions that would help us verify the test data structure.


After analyzing the test files and related code, I can now provide a final response:

Test data structure matches Bluesky API format

The test data structure in test-event.mjs is valid and consistent with the Bluesky API format based on the following evidence:

  1. Both test files (new-timeline-posts/test-event.mjs and new-posts-by-author/test-event.mjs) maintain consistent structure with identical field names and types.
  2. The structure follows Bluesky's AT Protocol conventions:
    • Correct URI format: at://did:plc:[identifier]/app.bsky.feed.post/[id]
    • Proper type identifiers: app.bsky.feed.post and app.bsky.feed.defs#postView
  3. The app implementation in bluesky.app.mjs confirms the API endpoints and resource types used in the test data:
    • Uses /app.bsky.feed.* endpoints
    • Handles post URIs in the same format
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the test data structure matches the Bluesky API schema

# Search for Bluesky API schema definitions in the codebase
rg -A 10 "app.bsky.feed.defs#postView" --type js

Length of output: 48


Script:

#!/bin/bash
# Let's try a different approach to find Bluesky API related schema or type definitions

# Search for files containing Bluesky API related patterns
rg -l "app\.bsky\.feed\." --type js

# Search for type definitions or schemas
rg "interface.*Post" --type ts
rg "type.*Post" --type ts

# Look for test files that might contain similar structures
fd "test.*\.(js|ts|mjs)$" --exec grep -l "app.bsky.feed"

Length of output: 1694


Script:

#!/bin/bash
# Let's examine the test files we found and other Bluesky-related files

# Check the content of both test files to compare structures
cat ./components/bluesky/sources/new-timeline-posts/test-event.mjs
cat ./components/bluesky/sources/new-posts-by-author/test-event.mjs

# Look for any type definitions or schemas in the Bluesky component
fd "." components/bluesky --type f --exec grep -l "type\|interface\|schema"

Length of output: 9104


Script:

#!/bin/bash
# Let's check the content of the Bluesky app file for any schema definitions
cat components/bluesky/bluesky.app.mjs

# Also check the polling common file which might contain type definitions
cat components/bluesky/sources/common/polling.mjs

Length of output: 7068

components/bluesky/bluesky.app.mjs (2)

1-3: LGTM! Appropriate imports for Pipedream component.

Using the platform's axios instance and organizing common utilities in separate modules follows good practices.


83-109: Verify API endpoint paths against Bluesky documentation.

Let's ensure all API endpoint paths match the latest Bluesky API documentation.

✅ Verification successful

Let me gather more information about the API endpoints by checking against the official Bluesky Lexicon files.


Let me verify the API endpoints against the official Bluesky documentation.


Based on the verification results, I can now provide the final response:

All API endpoints match the official Bluesky protocol specification

The implemented endpoints follow the correct namespace conventions and paths:

  • AT Protocol endpoints use com.atproto.* namespace:
    • /com.atproto.repo.createRecord
    • /com.atproto.repo.getRecord
    • /com.atproto.identity.resolveHandle
  • Bluesky Social endpoints use app.bsky.* namespace:
    • /app.bsky.feed.getAuthorFeed
    • /app.bsky.feed.getTimeline
    • /app.bsky.graph.getFollowers

The test files and constants also show consistent usage of these namespaces throughout the codebase, confirming the correct implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Extract and verify API endpoints against known patterns

# Extract all API endpoints
echo "Extracting API endpoints from the file:"
rg -o '/[a-zA-Z0-9.]+\.[a-zA-Z0-9.]+\.[a-zA-Z0-9.]+' components/bluesky/bluesky.app.mjs

# Known endpoint prefixes that should be present
echo -e "\nVerifying required endpoint prefixes:"
for prefix in "com.atproto" "app.bsky"; do
  if ! rg -q "/${prefix}" components/bluesky/bluesky.app.mjs; then
    echo "Warning: No endpoints found with prefix ${prefix}"
  fi
done

Length of output: 662


Script:

#!/bin/bash
# Search for lexicon files that might contain API definitions
echo "Searching for lexicon files:"
fd lexicon

# Check if there's any documentation about API endpoints
echo -e "\nSearching for API documentation:"
fd -e md -e txt | xargs rg -l "API|Endpoint" || true

# Look for any configuration files that might contain API endpoint definitions
echo -e "\nSearching for config files with endpoint definitions:"
fd -e json -e yaml -e yml | xargs rg -l "com\.atproto|app\.bsky" || true

Length of output: 65952


Script:

#!/bin/bash
# Check for any Bluesky API documentation or configuration in the component
echo "Checking Bluesky component documentation and configuration:"
rg -A 5 "API|endpoint|com\.atproto|app\.bsky" components/bluesky/ || true

# Look for any test files that might contain endpoint validations
echo -e "\nChecking for test files:"
fd -e test.js -e test.mjs -e spec.js -e spec.mjs components/bluesky/ || true

# Extract all method names and their corresponding endpoints
echo -e "\nExtracting method-endpoint mappings:"
rg "path: \"/.+\"" components/bluesky/bluesky.app.mjs -A 1

Length of output: 21035

@jcortes jcortes force-pushed the bluesky-new-components branch from 3a96ff7 to 0af5918 Compare December 31, 2024 20:06
Copy link
Contributor

@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

♻️ Duplicate comments (1)
components/bluesky/bluesky.app.mjs (1)

111-169: ⚠️ Potential issue

Add safeguard against infinite loops in pagination.

The while loop in getIterations could potentially run indefinitely if the cursor remains unchanged.

Apply this diff to add a safety check:

         }

+        if (cursor === response.cursor) {
+          console.log("Cursor unchanged, preventing infinite loop");
+          return;
+        }
         cursor = response.cursor;
       }

Additionally, consider extracting the resource processing logic into a separate method for better maintainability:

+    _processResource(resource, { lastDateAt, dateField, resourcesCount, max }) {
+      const isLastDateGreater = lastDateAt
+        && Date.parse(lastDateAt) > Date.parse(utils.getNestedProperty(resource, dateField));
+
+      if (isLastDateGreater) {
+        console.log(`Last date is greater than the current resource date in ${dateField}`);
+        return { shouldStop: true };
+      }
+
+      if (!isLastDateGreater) {
+        resourcesCount += 1;
+      }
+
+      if (resourcesCount >= max) {
+        console.log("Reached max resources");
+        return { shouldStop: true };
+      }
+
+      return { shouldStop: false, shouldYield: !isLastDateGreater, resourcesCount };
+    }
🧹 Nitpick comments (3)
components/bluesky/bluesky.app.mjs (2)

26-40: Enhance error message for invalid URLs.

The error message could be more informative by including the invalid URL in the message.

-      if (!match) {
-        throw new Error("Invalid post URL");
+      if (!match) {
+        throw new Error(`Invalid post URL: ${postUrl}. Expected format: https://bsky.app/profile/handle.bsky.social/post/id`);

56-64: Add request timeout configuration.

Consider adding a timeout configuration to prevent hanging requests.

     _makeRequest({
-      $ = this, path, headers, ...args
+      $ = this, path, headers, timeout = 10000, ...args
     } = {}) {
       return axios($, {
         ...args,
         url: this.getUrl(path),
         headers: this.getHeaders(headers),
+        timeout,
       });
     }
components/bluesky/sources/new-posts-by-author/new-posts-by-author.mjs (1)

40-47: Enhance date parsing robustness

The generateMeta method could benefit from more robust date parsing:

  1. Add validation for the createdAt timestamp
  2. Consider using a date parsing library for better cross-browser compatibility
 generateMeta(resource) {
   const { post } = resource;
+  const createdAt = post?.record?.createdAt;
+  if (!createdAt) {
+    throw new Error("Invalid post: missing creation timestamp");
+  }
   return {
     id: post.cid,
-    summary: `New Post at ${post.record.createdAt}`,
-    ts: Date.parse(post.record.createdAt),
+    summary: `New Post at ${createdAt}`,
+    ts: new Date(createdAt).getTime(),
   };
 };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3a96ff7 and 0af5918.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • components/bluesky/actions/create-post/create-post.mjs (1 hunks)
  • components/bluesky/actions/like-post/like-post.mjs (1 hunks)
  • components/bluesky/actions/retrieve-thread/retrieve-thread.mjs (1 hunks)
  • components/bluesky/bluesky.app.mjs (1 hunks)
  • components/bluesky/common/constants.mjs (1 hunks)
  • components/bluesky/common/utils.mjs (1 hunks)
  • components/bluesky/package.json (2 hunks)
  • components/bluesky/sources/common/polling.mjs (1 hunks)
  • components/bluesky/sources/new-follower-on-account/new-follower-on-account.mjs (1 hunks)
  • components/bluesky/sources/new-follower-on-account/test-event.mjs (1 hunks)
  • components/bluesky/sources/new-posts-by-author/new-posts-by-author.mjs (1 hunks)
  • components/bluesky/sources/new-posts-by-author/test-event.mjs (1 hunks)
  • components/bluesky/sources/new-timeline-posts/new-timeline-posts.mjs (1 hunks)
  • components/bluesky/sources/new-timeline-posts/test-event.mjs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (12)
  • components/bluesky/sources/new-posts-by-author/test-event.mjs
  • components/bluesky/actions/create-post/create-post.mjs
  • components/bluesky/common/utils.mjs
  • components/bluesky/package.json
  • components/bluesky/sources/new-follower-on-account/test-event.mjs
  • components/bluesky/actions/like-post/like-post.mjs
  • components/bluesky/actions/retrieve-thread/retrieve-thread.mjs
  • components/bluesky/sources/new-follower-on-account/new-follower-on-account.mjs
  • components/bluesky/sources/new-timeline-posts/new-timeline-posts.mjs
  • components/bluesky/sources/new-timeline-posts/test-event.mjs
  • components/bluesky/sources/common/polling.mjs
  • components/bluesky/common/constants.mjs
🔇 Additional comments (4)
components/bluesky/bluesky.app.mjs (1)

1-24: LGTM! Well-structured prop definitions with clear documentation.

The imports and prop definitions are well-organized. The descriptions are clear and helpful for users.

Let's verify the referenced regex pattern:

✅ Verification successful

URL regex pattern is properly defined and used consistently

The regex pattern HANDLE_AND_POST_ID_REGEX is correctly defined in the constants file and matches the expected URL format mentioned in the postUrl prop description (https://bsky.app/profile/myhandle.bsky.social/post/3le7x3qgmaw23). The pattern:

  • Handles both HTTP and HTTPS URLs
  • Makes the protocol and www optional
  • Captures the handle and postId in named groups
  • Properly validates the URL structure
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the regex pattern used for URL validation

# Check the constants file for the regex pattern
rg -A 1 "HANDLE_AND_POST_ID_REGEX" ./components/bluesky/common/constants.mjs

Length of output: 248

components/bluesky/sources/new-posts-by-author/new-posts-by-author.mjs (3)

49-49: LGTM!

The sample emit configuration is correctly implemented.


12-20: Verify the authorId propDefinition implementation

The component correctly extends common props and references the authorId propDefinition. Let's ensure the referenced propDefinition exists in the common app module.

✅ Verification successful

The authorId propDefinition is correctly implemented

The verification confirms that the authorId propDefinition is properly defined in components/bluesky/bluesky.app.mjs with appropriate type, label, and description. The reference in the new-posts-by-author component is valid and correctly used.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the authorId propDefinition in the common app module
# Expected: The propDefinition should be properly defined

# Search for authorId propDefinition in common files
rg -A 5 "authorId" components/bluesky/

Length of output: 1730


1-2: Verify the test event implementation

The module imports a test event from a local file. Let's ensure it provides appropriate test data for the Bluesky post format.

✅ Verification successful

Test event implementation provides appropriate Bluesky post data structure

The test event implementation in test-event.mjs contains a well-structured mock data object that accurately represents the Bluesky post format, including:

  • Complete post structure with URI, CID, author details, and content
  • Proper reply thread structure with root and parent posts
  • Appropriate metadata fields like timestamps, counts, and viewer state
  • Realistic mock data that maintains referential integrity across the thread
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the test event implementation
# Expected: The test event should contain sample Bluesky post data

# Check if the test event file exists and view its contents
cat components/bluesky/sources/new-posts-by-author/test-event.mjs

Length of output: 4157

Comment on lines +44 to +46
getDID() {
return this.$auth.did;
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for missing DID.

The method assumes this.$auth.did is always present. Consider adding validation.

   getDID() {
+    if (!this.$auth.did) {
+      throw new Error("DID not found in authentication context");
+    }
     return this.$auth.did;
   }
📝 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.

Suggested change
getDID() {
return this.$auth.did;
},
getDID() {
if (!this.$auth.did) {
throw new Error("DID not found in authentication context");
}
return this.$auth.did;
},

Comment on lines +32 to +39
getResourcesFnArgs() {
return {
debug: true,
params: {
actor: this.authorId,
},
};
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove debug flag from production code

The getResourcesFnArgs method includes a debug flag set to true. This should be removed or configured based on the environment.

 getResourcesFnArgs() {
   return {
-    debug: true,
     params: {
       actor: this.authorId,
     },
   };
 }
📝 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.

Suggested change
getResourcesFnArgs() {
return {
debug: true,
params: {
actor: this.authorId,
},
};
},
getResourcesFnArgs() {
return {
params: {
actor: this.authorId,
},
};
},

Comment on lines +6 to +11
key: "bluesky-new-posts-by-author",
name: "New Posts By Author",
description: "Emit new event when an author creates a post. Requires the author id as a prop to track posts from a specific author. [See the documentation](https://docs.bsky.app/docs/api/app-bsky-feed-search-posts).",
version: "0.0.1",
type: "source",
dedupe: "unique",
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Add CHANGELOG.md following repository format

The documentation link is valid, but version documentation is missing. The repository follows a clear changelog format that you should adopt:

  • Create a CHANGELOG.md in components/bluesky/ directory
  • Follow the established format:
    <!-- markdownlint-disable MD024 -->
    # Changelog
    
    ## [0.0.1] - <release-date>
    
    ### Added
    - Initial release of Bluesky components
    - New Posts By Author source component
🔗 Analysis chain

Add version changelog documentation

The component metadata is well-structured, but consider adding a CHANGELOG.md entry for this initial version.


Documentation link is valid, but changelog is missing

The API documentation link is accessible and returns a 200 status code, confirming it's valid. However, there's no CHANGELOG.md file in the bluesky components directory.

Let's verify if there's any changelog documentation in other common locations or if there's an established pattern for version documentation in the repository:


Consider adding version documentation

While the API documentation link is valid, there's no version documentation for the Bluesky components. The repository does maintain changelogs for other packages (packages/sdk and packages/connect-react), suggesting this is a common practice.

  • Consider adding a CHANGELOG.md in the components/bluesky directory to track version changes
  • Alternatively, add version history in a README.md file following the repository's established patterns

Let's check these existing changelogs to understand the preferred format:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the documentation link and check for changelog
# Expected: Documentation link should be valid and changelog should exist

# Check if the API documentation URL is accessible
curl -I https://docs.bsky.app/docs/api/app-bsky-feed-search-posts

# Check if there's a changelog for components
fd -g "CHANGELOG.md" components/bluesky/

Length of output: 913


Script:

#!/bin/bash
# Check for changelog patterns in the repository
fd -g "CHANGELOG*" .

# Check for version documentation in README files
fd -g "README*" components/bluesky/

Length of output: 126


Script:

#!/bin/bash
# Check the format of existing changelogs
head -n 10 packages/sdk/CHANGELOG.md
head -n 10 packages/connect-react/CHANGELOG.md

Length of output: 534

@jcortes jcortes merged commit 40dff13 into master Dec 31, 2024
11 checks passed
@jcortes jcortes deleted the bluesky-new-components branch December 31, 2024 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
action New Action Request trigger / source New trigger / source request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Components] bluesky
2 participants