Skip to content

Conversation

@luancazarine
Copy link
Collaborator

@luancazarine luancazarine commented Sep 30, 2025

Resolves #17540

Summary by CodeRabbit

  • New Features

    • Added QR generators for Text, URL, Email, SMS, Phone Call, Google Maps, WiFi, and vCard.
    • New UI options and presets (sizes, quiet zones, error correction, patterns, gradients, colors, logo/poster overlays, formats, auth options).
    • Utility to clean parameter payloads before requests.
  • Refactor

    • Redesigned QR API integration for safer request handling and reduced exposure of auth keys.
  • Chores

    • Package bumped to 0.1.0 and runtime dependency added.

…g various QR codes (email, Google Maps, phone call, SMS, text, URL, vCard, and WiFi), and introduce common utility functions and constants for QR code generation.
@luancazarine luancazarine linked an issue Sep 30, 2025 that may be closed by this pull request
@vercel
Copy link

vercel bot commented Sep 30, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
pipedream-docs Ignored Ignored Oct 1, 2025 3:35pm
pipedream-docs-redirect-do-not-edit Ignored Ignored Oct 1, 2025 3:35pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 30, 2025

Walkthrough

Adds a QR code generation feature: shared base action, multiple specific QR creation actions (text, URL, email, phonecall, SMS, WiFi, Google Maps, vCard), centralized constants and utils, and app helpers to call the QR API, save returned binary images to /tmp, and return file metadata.

Changes

Cohort / File(s) Summary of changes
Common base & utilities
components/qr_api/actions/common/base.mjs, components/qr_api/common/utils.mjs, components/qr_api/common/constants.mjs
New shared action base defining extensive props and a run() that builds params, calls app.createQrcode, writes the returned ArrayBuffer to /tmp, and returns filename/filePath. Adds cleanObj utility and centralized option constants.
QR creation actions
components/qr_api/actions/create-text-qrcode/*, components/qr_api/actions/create-url-qrcode/*, components/qr_api/actions/create-email-qrcode/*, components/qr_api/actions/create-phonecall-qrcode/*, components/qr_api/actions/create-sms-qrcode/*, components/qr_api/actions/create-wifi-qrcode/*, components/qr_api/actions/create-googlemaps-qrcode/*, components/qr_api/actions/create-vcard-qrcode/*
New action modules that spread the common base and declare metadata, type-specific props, getType(), and getParams() to produce payloads for their respective QR types.
App helpers
components/qr_api/qr_api.app.mjs
Removed propDefinitions and authKeys. Added _baseUrl(), _params(), _makeRequest(), and createQrcode() to centralize authenticated API requests and response handling.
Package manifest
components/qr_api/package.json
Updated package version to 0.1.0 and added dependency "@pipedream/platform": "^3.1.0".

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Action as QR Action
  participant Base as common.base.run()
  participant App as qr_api.app
  participant API as QR API Service
  participant FS as Filesystem (/tmp)

  User->>Action: Provide inputs (props)
  Action->>Base: getType(), getParams()
  Base->>App: createQrcode({ type, params, responseType: arraybuffer })
  App->>API: HTTP /qrcode/{type}?api_key=...&params
  API-->>App: 200 ArrayBuffer (image)
  App-->>Base: ArrayBuffer
  Base->>FS: writeFile /tmp/{filename}.{format}
  Base-->>Action: { filename, filePath }
  Action-->>User: Summary + file metadata
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I nibble the bytes and hum a tune,
Stitching squares beneath the moon.
URLs, WiFi, contacts neat—
Into /tmp each code will meet.
Hop, hop, a rabbit's little feat. 🐇

Pre-merge checks and finishing touches

❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Title Check ⚠️ Warning Although the title references the issue number and QR API, it is too generic and does not clearly convey the primary change of adding a suite of QR code generation components and supporting modules, making it hard for teammates to understand the main contribution at a glance. Update the title to a concise descriptive sentence that summarizes the key contribution, such as “Add QR API component actions and utilities for generating QR codes.”
Linked Issues Check ⚠️ Warning The code implements only the QR code generation actions but does not include the polling sources for scan events or the actions for retrieving analytics and updating QR design as specified in issue #17540, so it does not fully meet the linked issue requirements. Add implementations for the qr-code-scanned, qr-code-generated, and scan-analytics-updated sources, as well as the get-qr-analytics and update-qr-design actions in order to satisfy all objectives of issue #17540.
Description Check ⚠️ Warning The pull request description does not follow the repository’s required template because it omits the “## WHY” section and any explanation of the motivation behind the changes, instead providing only a resolve reference, which is insufficient to inform reviewers of the intent. Expand the description to include the “## WHY” header with a clear explanation of why these QR API components were added and how they satisfy the linked issue objectives.
✅ Passed checks (2 passed)
Check name Status Explanation
Out of Scope Changes Check ✅ Passed All modifications relate directly to the QR API feature, including support modules, action definitions, and package updates, and there are no additions unrelated to the objectives of implementing the QR API components.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 17540-components-qr-api

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 930b09d and b024149.

📒 Files selected for processing (1)
  • components/qr_api/actions/create-email-qrcode/create-email-qrcode.mjs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/qr_api/actions/create-email-qrcode/create-email-qrcode.mjs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
  • GitHub Check: pnpm publish
  • GitHub Check: Lint Code Base

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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

🧹 Nitpick comments (9)
components/qr_api/common/utils.mjs (1)

2-15: Clarify array semantics (drop empty arrays or keep?)

Right now empty arrays are preserved. If the API rejects empty arrays, we can optionally strip them:

-    const isEmptyObject = value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0;
-    const shouldOmit = value == null || value === "" || isEmptyObject;
+    const isEmptyArray = Array.isArray(value) && value.length === 0;
+    const isEmptyObject = value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0;
+    const shouldOmit = value == null || value === "" || isEmptyArray || isEmptyObject;

Would you like this behavior? If yes, I’ll update and add tests.

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

71-102: De-duplicate identical eye-shape option sets to prevent drift

POSTER_EYE_SHAPE_OPTIONS is identical to EYE_PATTERN_OPTIONS. Alias instead of copying to keep them in sync.

-const POSTER_EYE_SHAPE_OPTIONS = [
-  "RECT_RECT",
-  "ROUND_RECT",
-  ...
-  "DARK_HUT",
-];
+const POSTER_EYE_SHAPE_OPTIONS = EYE_PATTERN_OPTIONS;

Also applies to: 118-149

components/qr_api/qr_api.app.mjs (1)

7-24: Auth style: query param vs Bearer header—pick the recommended one

Examples point to GET on https://qrapi.io/v2/qrcode/{type} with an API key in the query string, but support docs also show a Bearer flow to api.qrapi.io/create-qr-code. Please confirm the current recommendation and, if supported, move the key to an Authorization: Bearer header to avoid leaking credentials via URLs/logs.

  • Evidence of GET + query on v2: See examples page for /v2/qrcode/url. (qrapi.io)
  • Support doc showing Bearer + /create-qr-code: Verify if this applies to the same product/version. (support.qrapi.io)

If Bearer is supported, we can add:

_headers() { return { Authorization: `Bearer ${this.$auth.api_key}` }; }
// and include `headers: this._headers()` in axios opts, removing api_key from params
components/qr_api/actions/create-phonecall-qrcode/create-phonecall-qrcode.mjs (1)

12-17: Small UX + hygiene: clearer prop name/placeholder and trim before send

  • Consider renaming numberphoneNumber for clarity, and add a placeholder (e.g., “+14155552671”). Also trim input before sending.
   props: {
     ...common.props,
-    number: {
+    phoneNumber: {
       type: "string",
-      label: "Number",
-      description: "The phone number you want to encode in the QR Code.",
+      label: "Phone Number",
+      description: "Phone number to encode (E.164 recommended, e.g. +14155552671).",
+      placeholder: "+14155552671",
     },
   },
   methods: {
     ...common.methods,
     getType() {
       return "phonecall";
     },
     getParams() {
       return {
-        number: this.number,
+        number: String(this.phoneNumber).trim(),
       };
     },
   },

If renaming is undesirable, keep number but still apply trim() and add placeholder.

Also applies to: 23-27

components/qr_api/actions/create-wifi-qrcode/create-wifi-qrcode.mjs (1)

37-43: Consider cleaning undefined optional parameters.

The getParams method returns authentication and psk even when they're undefined. Depending on the API's requirements, you may want to strip undefined values to avoid sending null or undefined in the request payload.

If the API rejects undefined values, consider using a utility to clean the object:

     getParams() {
-      return {
+      const params = {
         ssid: this.ssid,
         authentication: this.authentication,
         psk: this.psk,
       };
+      // Assuming utils.cleanObj exists (as mentioned in AI summary)
+      return Object.fromEntries(
+        Object.entries(params).filter(([_, v]) => v !== undefined)
+      );
     },
components/qr_api/actions/create-email-qrcode/create-email-qrcode.mjs (1)

23-27: Consider validating email address format.

The email address is passed directly without validation. While the API might handle this, validating the format client-side provides faster feedback for invalid inputs.

     getParams() {
+      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+      if (!emailRegex.test(this.address)) {
+        throw new Error(`Invalid email address: ${this.address}`);
+      }
       return {
         address: this.address,
       };
     },
components/qr_api/actions/create-url-qrcode/create-url-qrcode.mjs (1)

23-27: Consider validating URL format.

The URL is passed without validation. Invalid URLs could result in QR codes that don't work as expected. Client-side validation provides immediate feedback.

     getParams() {
+      try {
+        new URL(this.url);
+      } catch (e) {
+        throw new Error(`Invalid URL: ${this.url}`);
+      }
       return {
         url: this.url,
       };
     },
components/qr_api/actions/create-text-qrcode/create-text-qrcode.mjs (1)

23-27: Consider validating text is not empty.

While the API likely validates QR code capacity limits, checking for empty text provides immediate user feedback for an obvious error case.

     getParams() {
+      if (!this.data || this.data.trim().length === 0) {
+        throw new Error("Text cannot be empty");
+      }
       return {
         data: this.data,
       };
     },
components/qr_api/actions/create-vcard-qrcode/create-vcard-qrcode.mjs (1)

12-16: Clarify the "Uname" label.

The label "Uname" is unclear and not user-friendly. Consider using "Full Name" or "Name" instead for better clarity.

Apply this diff:

-    uname: {
-      type: "string",
-      label: "Uname",
-      description: "Enter full name of contact you want encoded in the Vcard.",
-    },
+    uname: {
+      type: "string",
+      label: "Full Name",
+      description: "Enter full name of contact you want encoded in the Vcard.",
+    },
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61d0151 and 930b09d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (13)
  • components/qr_api/actions/common/base.mjs (1 hunks)
  • components/qr_api/actions/create-email-qrcode/create-email-qrcode.mjs (1 hunks)
  • components/qr_api/actions/create-googlemaps-qrcode/create-googlemaps-qrcode.mjs (1 hunks)
  • components/qr_api/actions/create-phonecall-qrcode/create-phonecall-qrcode.mjs (1 hunks)
  • components/qr_api/actions/create-sms-qrcode/create-sms-qrcode.mjs (1 hunks)
  • components/qr_api/actions/create-text-qrcode/create-text-qrcode.mjs (1 hunks)
  • components/qr_api/actions/create-url-qrcode/create-url-qrcode.mjs (1 hunks)
  • components/qr_api/actions/create-vcard-qrcode/create-vcard-qrcode.mjs (1 hunks)
  • components/qr_api/actions/create-wifi-qrcode/create-wifi-qrcode.mjs (1 hunks)
  • components/qr_api/common/constants.mjs (1 hunks)
  • components/qr_api/common/utils.mjs (1 hunks)
  • components/qr_api/package.json (2 hunks)
  • components/qr_api/qr_api.app.mjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
components/qr_api/common/utils.mjs (2)
components/openai/actions/create-transcription/create-transcription.mjs (1)
  • v (110-112)
components/akeneo/akeneo.app.mjs (1)
  • JSON (99-110)
components/qr_api/actions/common/base.mjs (1)
components/qr_api/common/utils.mjs (2)
  • cleanObj (1-16)
  • cleanObj (1-16)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Lint Code Base
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
  • GitHub Check: pnpm publish
🔇 Additional comments (8)
components/qr_api/package.json (1)

3-17: Version bump and dependency addition look good

No issues spotted with 0.1.0 and @pipedream/platform ^3.1.0. Ensure lockfile is updated in the root workspace.

components/qr_api/actions/create-wifi-qrcode/create-wifi-qrcode.mjs (1)

22-22: AUTHENTICATION_OPTIONS constant is defined—Found in components/qr_api/common/constants.mjs (lines 166–170) as ["WPA", "WEP", "unencrypted"].

components/qr_api/actions/create-vcard-qrcode/create-vcard-qrcode.mjs (1)

96-119: LGTM!

The methods correctly implement the required interface pattern. The getType() returns the appropriate QR code type, and getParams() properly maps all props to the API parameters.

components/qr_api/actions/common/base.mjs (2)

1-4: LGTM!

Imports are appropriate and correctly structured.


7-173: Well-documented props with helpful external references.

The prop descriptions are thorough and include useful tips and links to external documentation. This will help users understand how to configure QR codes effectively.

components/qr_api/actions/create-sms-qrcode/create-sms-qrcode.mjs (3)

1-9: LGTM!

Action metadata is correctly configured and follows the established pattern for QR API actions.


10-22: LGTM!

Props are well-defined with clear labels and descriptions. Both required fields are appropriately configured.


23-35: LGTM!

Methods correctly implement the required interface. The getType() returns "SMS" and getParams() properly maps camelCase props to snake_case API parameters.

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.

LGTM! Ready for QA!

@michelle0927
Copy link
Collaborator

@luancazarine @vunguyenhung Make sure annotations are added before this is merged! Slack context

@vunguyenhung vunguyenhung merged commit de76662 into master Oct 2, 2025
10 checks passed
@vunguyenhung vunguyenhung deleted the 17540-components-qr-api branch October 2, 2025 06:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Components] QR API

4 participants