Skip to content

pr05 Typescript #3: Migrate client/utils folder #3553

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

Open
wants to merge 45 commits into
base: develop
Choose a base branch
from

Conversation

clairep94
Copy link
Collaborator

@clairep94 clairep94 commented Jul 26, 2025

pr05 Typescript Migration 3: Migrate the client/utils folder

IMPORTANT: Should be reviewed after #3540 for clarity

Context:

  • Rebuild of Pr05/migrate client utils clairep94/p5.js-web-editor#5 --> forgot to do git mv for the first few files and directly renamed, so this looks like deleting and creating a new file for git, and erases the previous history.

  • Migrate as much of the client/utils folder with the following steps:

  1. git mv someUtil.js someUtil.ts. If possible, commit without the no-verify flag, otherwise with no-verify.
    I forgot to add no-verify to my commit message in some of these initial ones
  2. Add unit test to secure current behaviour
  3. Check for all instances of useage for the utility function to determine types & edgecases of types
  4. Add types & handle edgecases & update test
  5. Refactor if beneficial
  6. Add JSDocs
  • I skipped the intellisense autogen files & the codemirror utility files due to unfamiliarity, but migrated most of the rest of the folder

Changes:

Please see annotations on files

  • apiClient
  • device
  • metaKey
  • language-utils
  • formatDate
  • consoleUtils
  • dispatcher
  • evaluateExpression
  • reduxFormUtils
  • getConfig (+ many instances of useage throughout the client folder)
  • NEW: parseStringToType

Notes:

I have verified that this pull request:

  • has no linting errors (npm run lint)
  • has no test errors (npm run test)
  • is from a uniquely-named feature branch and is up to date with the develop branch.
  • is descriptively named and links to an issue number, i.e. Fixes #123

clairep94 and others added 30 commits July 15, 2025 22:30
@clairep94 clairep94 changed the title Pr05/migrate client utils folder pr05 Typescript #3: Migrate client/utils folder Jul 26, 2025
@clairep94 clairep94 added the pr05 Grant Projects pr05 Grant Projects label Jul 27, 2025
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

update to use isMac() utility -- does same thing as the old line 33-34, so removes repeated code

@@ -15,7 +15,7 @@ import {
} from './ide';
import { clearState, saveState } from '../../../persistState';

const ROOT_URL = getConfig('API_URL');
const ROOT_URL = getConfig('API_URL', { nullishString: 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.

updated this to return a '' if no API_URL is found --> used in ln261 as a template literal so it was previously doing

const win = window.open(`${undefined}/projects/${projectId}/zip`, '_blank');

which would give:

window.open(`undefined/projects/${projectId}/zip`, '_blank'))

@@ -307,6 +307,8 @@ export function cloneProject(project) {
(file, callback) => {
if (
file.url &&
S3_BUCKET &&
S3_BUCKET_URL_BASE &&
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added this check for safety because I think str.includes(undefined) runs the same as str.includes("undefined")
so

"foo undefined bar".includes(undefined); // true

nullishString: true
})}.amazonaws.com/${getConfig('S3_BUCKET', {
nullishString: 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.


const limit = getConfig('UPLOAD_LIMIT') || 250000000;
const limit = parseNumber(getConfig('UPLOAD_LIMIT')) || 250000000;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Use the new parseNumber utility to transform the string from getConfig to a number

Currently this file is still jsx so it would be ok to use the string version of this number, but it's not as safe

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Refactor the portions of using getConfig for readability instead of inline

use new parseBoolean function to parse the string val of getConfig to a boolean instead
I wonder if this file was previously only checking if process.env.LOGIN_ENABLED had a value??

So if the env file looked like:

LOGIN_ENABLED=false
UI_COLLECTIONS_ENABLED=false

getConfig('LOGIN_ENABLED') // "false"
!getConfig('LOGIN_ENABLED') // false??

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

tried my best with this test, I'm not 100% sure how the line offset works, so I didn't test its calculation, just that it should be a number in the tupple that's returned

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

PR > Files changed view on Github shows that this is a delete + new file, due to too many changes from the original due to refactoring, so let me know if it would be preferable to go back to the unrefactored!

I refactored for readability & handling the edgecase of not having a navigator or navigator.userAgent, but that might be excessive

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Similar to above, GH shows this in PR mode as a deletion + new file, but it seems the history is still retained when you view git blame:
https://github.com/processing/p5.js-web-editor/blame/2362807016746d3b3798085437c2406db2d31757/client/utils/dispatcher.ts

Kept in the comments from a previous maintainer & added JSDocs. I think the number of new lines of jsdocs made it pass the diff tolerated percentage before github shows it as a file deletion instead of a file update

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No changes other than adding types & no refactors on this one

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not 100% sure if these tests match the function's useage on previewEntry and if there are other cases that need to be added?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Small refactor for readability + added JSDocs. History is retained despite looking like a delete + new file here
https://github.com/processing/p5.js-web-editor/blame/2362807016746d3b3798085437c2406db2d31757/client/utils/formatDate.ts

Did small refactor to return '' early if !parsed

Also corrected what I thought was a typo here:
https://github.com/processing/p5.js-web-editor/pull/3553/files#diff-e2130c2674d12d8f2724335d2d8d2b7ade8d366efa4bf42717c2af4eec4fa6aaL28

const diffInMs = differenceInMilliseconds(now, parsed);

      if (Math.abs(diffInMs < 10000)) {
        return i18next.t('formatDate.JustNow');
      } else if (diffInMs < 20000) {
        return i18next.t('formatDate.15Seconds');
      } else if (diffInMs < 30000) {
        return i18next.t('formatDate.25Seconds');
      } else if (diffInMs < 46000) {
        return i18next.t('formatDate.35Seconds');
      }

It seems like they're using Math.abs incorrectly --> it's using Math.abs(true) // 1 and Math.abs(false) // 0

I updated to be :

const diffInMs = Math.abs(differenceInMilliseconds(now, parsed));

// rest of checks for what range the absolute diff between now and the time something happened falls under

Copy link
Collaborator Author

@clairep94 clairep94 Jul 28, 2025

Choose a reason for hiding this comment

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

History retained here:
https://github.com/processing/p5.js-web-editor/blame/2362807016746d3b3798085437c2406db2d31757/client/utils/getConfig.ts

Refactors:

For when we want a number or boolean I added a new utility file called parseStringToType below

  • I was going to do the parsing within getConfig, as I did with my proof-of-concept PR from my grant application, but I thought actually keeping the parsing in a separate function keeps things more modular and testable & keeps the return types of getConfig consistent for predictability

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

History retained here:
https://github.com/processing/p5.js-web-editor/blame/2362807016746d3b3798085437c2406db2d31757/client/utils/language-utils.ts

Create a unit test to secure all behaviour for this function prior to refactor, then did a refactor to make the long for-loop & nested if-statements more readable

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this old implementation uses navigator.platform which is deprecated:
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform

I updated this file to use utils/device to determine if the client is using a mac

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

New utility functions to parse a string (from getConfig) to a specified type:

for parseNumber it returns a number if parseable or undefined/0 depending on the nullishNumber flag

for parseBoolean it returns a boolean if parseable or undefined/false depending on the nullishBoolean flag

Copy link
Collaborator Author

@clairep94 clairep94 Jul 28, 2025

Choose a reason for hiding this comment

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

History retained here:
https://github.com/processing/p5.js-web-editor/blame/2362807016746d3b3798085437c2406db2d31757/client/utils/reduxFormUtils.ts

  • Moved the username regex to top of file for readability

  • Changed the username length check to .length instead of regex for readability: https://github.com/processing/p5.js-web-editor/pull/3553/files#diff-932633409951987d095611a326d0b6b624bd482b07f1e27a9ca7987f6b52a71bR32

  • Moved the internal helper functions higher, and grouped the public functions together on the bottom of the file

  • Added types -- let me know if this organisation makes sense as this was the most stylistic/open-ended thing I did on the PR

  • Also not sure if we want to have a root/types folder, or if it makes sense to keep types collocated where they are most used, and potentially exported, as I did here?

  • No other refactors in each function internally

@clairep94 clairep94 marked this pull request as ready for review July 28, 2025 12:14
@clairep94
Copy link
Collaborator Author

@khanniie @raclim Ready for review! I tried to annotate the files with comments to provide context / explainations for any refactors, but let me know if we should do a sync-review of this one since it's so big

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr05 Grant Projects pr05 Grant Projects
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant