Skip to content

fix: URL reference error#469

Merged
ahochsteger merged 7 commits intomainfrom
fix/456/url-reference-error
Feb 6, 2025
Merged

fix: URL reference error#469
ahochsteger merged 7 commits intomainfrom
fix/456/url-reference-error

Conversation

@ahochsteger
Copy link
Owner

@ahochsteger ahochsteger commented Jan 30, 2025

Description

This PR fixes the URL ReferenceError, since URL is not defined in the Google Apps Script environment.

It replaces the call to URL.canParse() with a custom implementation isValidURL() that does a simple RegEx check instead without having to polyfill the missing API.

Fixes #456

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)

How has this been tested?

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing tests pass locally with my changes

resolves ERROR Action thread.exportAsPdf caused an error: ReferenceError: URL is not defined #456
* now uses data urls to trigger the URL ReferenceError
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 6, 2025

@ahochsteger ahochsteger merged commit aff2c13 into main Feb 6, 2025
6 checks passed
@ahochsteger ahochsteger deleted the fix/456/url-reference-error branch February 9, 2025 15:27
@ahochsteger
Copy link
Owner Author

/gemini help

@gemini-code-assist
Copy link

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

@ahochsteger
Copy link
Owner Author

/gemini summary

@gemini-code-assist
Copy link

Summary of Changes

This pull request addresses an issue where the URL constructor is not defined in the Google Apps Script environment, causing a ReferenceError. To resolve this, the PR replaces the URL.canParse() call with a custom isValidURL() function that uses a regular expression to validate URLs. Additionally, the PR includes updates to dependencies and build configurations, and addresses several potential null reference issues.

Highlights

  • Fix: URL ReferenceError: Replaces the URL.canParse() call with a custom isValidURL() function for URL validation in Google Apps Script.
  • Dependency Updates: Updates several dependencies in package-lock.json and package.json, including adding @rollup/plugin-terser and rollup-plugin-google-apps-script.
  • Build Configuration: Modifies rollup.config.mjs to include plugins like analyzer, terser, and visualizer for improved build processes.
  • Null Reference Safety: Addresses potential null reference issues by adding checks and optional chaining in EnvProvider.ts, ActionRegistry.ts, AttachmentActions.spec.ts, GDriveAdapter.ts, GmailAdapter.ts, Config.ts, and BaseProcessor.ts.
  • E2E Test Enhancement: Enhances the E2E test actionExport.ts by adding an inline data URI image to the email body to test image processing.

Changelog

Click here to see the changelog
  • eslint.config.mjs
    • Disables the @typescript-eslint/no-extraneous-class rule to avoid refactoring classes with only static methods.
  • package-lock.json
    • Updates dependencies, including adding @rollup/plugin-terser, rollup-plugin-analyzer, rollup-plugin-google-apps-script, and rollup-plugin-visualizer.
    • Removes gas-entry-generator and its dependencies.
  • package.json
    • Updates devDependencies, including adding @rollup/plugin-terser, rollup-plugin-analyzer, rollup-plugin-google-apps-script, and rollup-plugin-visualizer.
    • Removes rollup-plugin-gas.
  • rollup.config.mjs
    • Adds plugins like analyzer, terser, and visualizer to the Rollup configuration for build analysis and minification.
    • Replaces rollup-plugin-gas with rollup-plugin-google-apps-script and configures its options.
  • src/examples/actions/actionExport.ts
    • Adds an inline data URI image to the email body for E2E testing.
  • src/gas/examples/actions/actionExport-test.js
    • Adds an inline data URI image to the email body for testing.
  • src/lib/Context.ts
    • Exports the MetaInfoEntry type and makes the value in MetaInfo optional to handle cases where meta information might be undefined.
  • src/lib/EnvProvider.ts
    • Removes optional chaining when accessing packageInfo.name and packageInfo.version.
    • Removes optional chaining when accessing Session.getScriptTimeZone().
  • src/lib/actions/ActionRegistry.ts
    • Adds eslint-disable comments to suppress @typescript-eslint/no-unnecessary-condition warnings.
  • src/lib/actions/AttachmentActions.spec.ts
    • Adds optional chaining when accessing result.actionMeta values to handle cases where the value might be undefined.
  • src/lib/adapter/GDriveAdapter.ts
    • Adds eslint-disable comments to suppress @typescript-eslint/no-unnecessary-condition warnings.
  • src/lib/adapter/GmailAdapter.ts
    • Adds a comment noting a type issue in the upstream typedef for getUserLabelByName().
    • Adds eslint-disable comments to suppress @typescript-eslint/no-unnecessary-condition warnings.
  • src/lib/adapter/GmailExportAdapter.spec.ts
    • Adds a new test case to process data URLs in HTML.
    • Imports GMailMocks from ../../test/mocks/GMailMocks.
  • src/lib/adapter/GmailExportAdapter.ts
    • Adds a isValidUrl method to validate URLs using a regular expression.
    • Replaces URL.canParse() with this.isValidUrl() for URL validation.
    • Adds a warning log when fetching an avatar fails.
    • Removes .filter((blob) => blob) when processing images.
  • src/lib/adapter/LogAdapter.ts
    • Removes optional chaining when accessing field.ctxValues.
  • src/lib/adapter/SpreadsheetAdapter.ts
    • Changes the argument type of appendToLogSheet and initLogSheet to string[].
    • Joins the arguments with a comma when logging an error in appendToLogSheet.
  • src/lib/config/Config.ts
    • Removes optional chaining when accessing config.threads and config.attachments.
  • src/lib/config/ThreadConfig.ts
    • Removes optional chaining when accessing config.attachments.
  • src/lib/e2e/E2E.spec.ts
    • Adds new test cases for expect() and statusMapFromResults().
    • Removes optional chaining when accessing globals.repoBaseUrl.
  • src/lib/e2e/E2E.ts
    • Removes optional chaining when accessing globals.repoBaseUrl.
    • Logs the error message as a string.
  • src/lib/expr/ExprEvaluator.ts
    • Removes /* eslint-disable @typescript-eslint/no-extraneous-class */.
    • Moves import { Context, MetaInfo } from "./../Context" to after the antlr4ng imports.
  • src/lib/expr/ExprFilter.ts
    • Removes the spread operator from the args property of several filter functions.
  • src/lib/processors/AttachmentProcessor.ts
    • Removes RegexUtils import and usage, replacing it with this.matchesRules.
    • Implements matchesRules to consolidate match logic.
  • src/lib/processors/BaseProcessor.spec.ts
    • Adds new test cases for matchLabels().
  • src/lib/processors/BaseProcessor.ts
    • Adds new types for MatchRule and related types.
    • Adds matchLabels to test the labels.
    • Adds matchesRules to consolidate match logic.
    • Changes the argument type of isSet to boolean | number | string | null | undefined.
  • src/lib/processors/MessageProcessor.spec.ts
    • Removes the spread operator from the args property of several filter functions.
    • Implements matchesRules to consolidate match logic.
  • src/lib/processors/MessageProcessor.ts
    • Removes RegexUtils import and usage, replacing it with this.matchesRules.
    • Implements matchesRules to consolidate match logic.
  • src/lib/processors/ThreadProcessor.spec.ts
    • Adds new test cases for match().
  • src/lib/processors/ThreadProcessor.ts
    • Removes RegexUtils import and usage, replacing it with this.matchesRules.
    • Implements matchesRules to consolidate match logic.
  • src/lib/utils/ConfigUtils.ts
    • Makes the essentialFn argument in essentialProp optional.
  • src/lib/utils/Decorators.ts
    • Removes optional chaining when accessing args[0].
  • src/lib/utils/Logger.ts
    • Removes /* eslint-disable @typescript-eslint/no-explicit-any */.
    • Logs the message as a string.
  • src/lib/utils/RegexUtils.ts
    • Changes the return type of matchRegExp to RegExpExecArray | null.
    • Adds a null check to the str argument in matchRegExp.
  • src/test/docs/update-docs.spec.ts
    • Adds a null check to m[k] before accessing its properties.

Activity

  • SonarQube Cloud analysis passed, indicating no new issues, security hotspots, or code duplications.
  • Author @ahochsteger requested Gemini Code Assist help.
  • Author @ahochsteger requested a summary of the pull request.

@ahochsteger
Copy link
Owner Author

/gemini review

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This PR addresses a critical issue where the URL API is not available in the Google Apps Script environment. The solution replaces the URL.canParse() call with a custom isValidURL() function that uses a regular expression for URL validation. This approach avoids the need for polyfills and resolves the ReferenceError. The changes are well-documented and include a test case to ensure the fix is effective. The addition of rollup plugins for bundle analysis and minification is also a good step towards optimizing the library.

Summary of Findings

  • Potential performance impact of regular expression: The isValidURL() function uses a regular expression for URL validation. While this resolves the immediate issue, it's important to consider the performance implications of this approach, especially if it's used frequently. Complex regular expressions can be computationally expensive, and it might be worthwhile to explore alternative validation methods if performance becomes a concern. I did not add a review comment for this since I was instructed not to comment on low severity issues.
  • Unnecessary condition checks: There are several instances where eslint-disable-next-line @typescript-eslint/no-unnecessary-condition is used to suppress warnings about potentially unnecessary condition checks. While these suppressions might be valid in the current context, it's important to ensure that the conditions are indeed necessary and that the code behaves as expected in all cases. It might be beneficial to revisit these conditions and refactor the code to eliminate the need for the suppressions. I did not add review comments for this since I was instructed not to comment on low severity issues.

Merge Readiness

The pull request addresses a critical issue and includes a test case to ensure the fix is effective. The changes are well-documented and the code is generally well-structured. I recommend merging this pull request after addressing the high severity issue related to the missing return type annotation for the isValidUrl function.

Comment on lines +84 to +86
protected isValidUrl(urlString: string): boolean {
const urlRegex = /^(?:(?:https?|data):\/\/[^\s]+)$/
return urlRegex.test(urlString)

Choose a reason for hiding this comment

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

high

Consider adding a return type annotation to the isValidUrl function to improve code clarity and prevent unexpected behavior. The return type should be boolean.

Suggested change
protected isValidUrl(urlString: string): boolean {
const urlRegex = /^(?:(?:https?|data):\/\/[^\s]+)$/
return urlRegex.test(urlString)
protected isValidUrl(urlString: string): boolean {

rules: {
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-extraneous-class": "warn",
"@typescript-eslint/no-extraneous-class": "off", // Reason: Requires refactoring classes with only static methods.

Choose a reason for hiding this comment

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

medium

It's good to see the reason for disabling this rule. However, consider if refactoring the classes with only static methods is feasible in the near future to re-enable this rule and improve code structure.

runMode: runMode,
session: Session,
timezone: Session?.getScriptTimeZone() || "Etc/UTC",
timezone: Session.getScriptTimeZone() || "Etc/UTC",

Choose a reason for hiding this comment

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

medium

Since Session.getScriptTimeZone() can return null, it's good to provide a default value to ensure that the timezone is always defined. However, consider logging a warning message if Session.getScriptTimeZone() returns null, as this might indicate a configuration issue.

Comment on lines 121 to 122
.map((att) => att.copyBlob())
.filter((blob) => blob)
// process all img tags which reference "attachments"

Choose a reason for hiding this comment

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

medium

The .filter((blob) => blob) call was removed. Can you confirm that this is intentional and that there are no cases where this filter is necessary to prevent errors?

(avatarBlob = this.getAvatar(
addressparser(message.getFrom())[0],
) as GoogleAppsScript.Base.Blob)
(avatarBlob = this.getAvatar(addressparser(message.getFrom())[0]))

Choose a reason for hiding this comment

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

medium

The type assertion as GoogleAppsScript.Base.Blob was removed. Can you confirm that this is intentional and that there are no type-related issues as a result of this change?

Comment on lines +463 to 465
[...(global ?? "").split(","), ...local.split(",")].map((v) =>
v.trim(),
),

Choose a reason for hiding this comment

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

medium

It looks like you are using the split function without any arguments. Can you confirm that this is intentional and that there are no cases where this will cause issues?

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.

ERROR Action thread.exportAsPdf caused an error: ReferenceError: URL is not defined

1 participant