Skip to content

fix: crypto.randomUUID causes React-Native build failures - #2858

Open
dplewis wants to merge 19 commits into
parse-community:alphafrom
dplewis:randomuuid
Open

fix: crypto.randomUUID causes React-Native build failures#2858
dplewis wants to merge 19 commits into
parse-community:alphafrom
dplewis:randomuuid

Conversation

@dplewis

@dplewis dplewis commented Jan 8, 2026

Copy link
Copy Markdown
Member

Pull Request

Issue

Using node:crypto prevented users from polyfilling randomUUID

Closes: #2856

Approach

As of Node 18 Web Crypto API is now a global object, this global object is also included in the browser. For any other runtime it will need to be polyfilled if not supported.

Summary by CodeRabbit

  • Bug Fixes
    • Simplified UUID generation and added a clear runtime error when secure UUID generation isn’t available.
  • Tests
    • Added a test confirming that attempting UUID generation without cryptographic support throws the expected descriptive error.

✏️ Tip: You can customize this high-level summary in your review settings.

@parse-github-assistant

parse-github-assistant Bot commented Jan 8, 2026

Copy link
Copy Markdown

🚀 Thanks for opening this pull request!

@coderabbitai

coderabbitai Bot commented Jan 8, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Consolidated UUID generation into a single const implementation that calls crypto.randomUUID() with a runtime guard that throws a descriptive error if unavailable; removed environment-specific branching and added a test for the missing-crypto case.

Changes

Cohort / File(s) Summary
Implementation
src/uuid.ts
Replaced environment-branching UUID logic with a single const uuid = (): string => { ... } that checks for crypto.randomUUID at runtime and throws a descriptive error if missing; returns crypto.randomUUID() otherwise.
Type Declarations
types/uuid.d.ts
Changed exported declaration from declare let uuid: () => string; to declare const uuid: () => string;. export default uuid; unchanged.
Tests
src/__tests__/browser-test.js
Added test "throw error if randomUUID is not available" which deletes global.crypto, requires the module, asserts the expected error is thrown, and restores global.crypto.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested reviewers

  • mtrezza
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: migrating from Node's crypto.randomUUID to a guarded global crypto implementation that resolves React-Native build failures.
Description check ✅ Passed The description includes the required issue link (#2856) and approach, but omits the checklist tasks (tests and documentation) which are typically expected in complete descriptions.
Linked Issues check ✅ Passed The PR successfully addresses issue #2856 by removing the direct Node crypto dependency, implementing a runtime guard for Web Crypto API, and allowing polyfills in environments without native support.
Out of Scope Changes check ✅ Passed All changes are directly scoped to resolving the React-Native uuid compatibility issue: uuid implementation refactoring, type declarations, and corresponding test additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@parseplatformorg

parseplatformorg commented Jan 8, 2026

Copy link
Copy Markdown
Contributor

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@codecov

codecov Bot commented Jan 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.98%. Comparing base (77862c5) to head (5267361).

Additional details and impacted files
@@            Coverage Diff             @@
##            alpha    #2858      +/-   ##
==========================================
- Coverage   99.98%   99.98%   -0.01%     
==========================================
  Files          64       64              
  Lines        6339     6329      -10     
  Branches     1522     1520       -2     
==========================================
- Hits         6338     6328      -10     
  Misses          1        1              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @README.md:
- Line 10: The Node.js version badge excludes v18 while the compatibility table
(lines ~54–57) still lists v18; update the badge string in README.md to include
18 (e.g., change "20,_22,_24" to "18,_20,_22,_24") and verify the compatibility
table and any other references now match the badge; alternatively, if you intend
to drop v18 support, remove it from the compatibility table instead—ensure both
the badge and table are consistent.
- Around line 97-99: Replace the ES6 import of the polyfill with the same
CommonJS style used elsewhere: change the line that imports
'react-native-random-uuid' so it uses require() rather than import, ensuring the
polyfill still provides crypto.randomUUID() globally; keep the surrounding
comment about Parse version comparison as-is until the exact version is
confirmed.

In @src/uuid.ts:
- Line 1: The uuid helper currently calls crypto.randomUUID() directly which
throws a cryptic ReferenceError when crypto or crypto.randomUUID is missing;
update the uuid function to perform a runtime check (typeof crypto !==
'undefined' && typeof crypto.randomUUID === 'function') and throw a clear,
actionable Error if unavailable that explains how to polyfill in React Native
(mention importing "react-native-random-uuid" after Parse.setAsyncStorage() and
link to the README), otherwise return crypto.randomUUID(); reference the
existing uuid function in src/uuid.ts to locate and replace the direct call.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf2ef13 and a79469c.

📒 Files selected for processing (2)
  • README.md
  • src/uuid.ts
⏰ 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). (3)
  • GitHub Check: build (Node 20, 20.19.0)
  • GitHub Check: build (Node 24, 24.1.0)
  • GitHub Check: build (Node 22, 22.12.0)

Comment thread README.md Outdated
Comment thread src/uuid.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @types/uuid.d.ts:
- Line 1: The current uuid implementation relies on crypto.randomUUID() which
will crash in React Native; update the module used by the declared function uuid
to provide a RN-safe implementation by either adding a React Native specific
file (e.g., create uuid.react-native.ts or lib/react-native/uuid.js) that
returns the same `${string}-${string}-...` format using a RN-friendly polyfill
(like react-native-uuid or the uuid package), or modify src/uuid.ts to detect
React Native at runtime and fall back to the polyfill when crypto.randomUUID is
unavailable; ensure InstallationController.currentInstallationId() and other
callers import the unified uuid symbol so RN builds pick up the RN variant or
the runtime fallback.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a79469c and 1b8aa51.

📒 Files selected for processing (3)
  • types/AnonymousUtils.d.ts
  • types/Parse.d.ts
  • types/uuid.d.ts
⏰ 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). (3)
  • GitHub Check: build (Node 24, 24.1.0)
  • GitHub Check: build (Node 20, 20.19.0)
  • GitHub Check: build (Node 22, 22.12.0)
🔇 Additional comments (2)
types/AnonymousUtils.d.ts (1)

79-79: LGTM! Type narrowing accurately represents UUID format.

The template literal type ${string}-${string}-${string}-${string}-${string} correctly represents the standard UUID format. Since this is within the _getAuthProvider() method (indicated by the _ prefix as a private API), the type narrowing has minimal breaking change risk.

types/Parse.d.ts (1)

36-36: LGTM! Consistent type narrowing across Parse namespace.

The type change for authData.id is consistent with the same change in types/AnonymousUtils.d.ts, maintaining type consistency across the Parse namespace declarations.

Comment thread types/uuid.d.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @README.md:
- Line 10: The README badge was updated to list Node 20, 22, 24 but the
compatibility table still lists Node 18; update the README to be consistent by
either removing Node 18 from the compatibility table to match the badge, or keep
Node 18 and add an explicit note that Node 18 requires a polyfill for global
crypto.randomUUID (requirement: Node >=19 provides it natively); reference the
badge token "[![Node Version]...]" and the compatibility table section and
ensure the README clearly states the native requirement (Node ≥19) or documents
how to provide the polyfill for Node 18 users.
🧹 Nitpick comments (3)
README.md (1)

89-97: Consider documenting the crypto polyfill requirement for React Native.

React Native users will now need to polyfill crypto.randomUUID since this PR removes the Node crypto import. Consider adding a note here to guide users, for example:

**Note:** React Native environments require a crypto polyfill. Install and import `react-native-random-uuid` or similar before initializing Parse.
src/__tests__/browser-test.js (1)

165-176: Improve cleanup reliability with try-finally.

The test correctly validates the error path, but if uuidv4() unexpectedly succeeds (line 171 fails), global.crypto won't be restored. Use a finally block to guarantee cleanup:

♻️ Suggested refactor
   it('throw error if randomUUID is not available', () => {
     const tmp = global.crypto;
     delete global.crypto;
     try {
       const uuidv4 = require('../uuid').default;
       uuidv4();
       expect(true).toBe(false);
     } catch (e) {
       expect(e.message).toBe('crypto.randomUUID is not available. For React Native, import "react-native-random-uuid"');
+    } finally {
+      global.crypto = tmp;
     }
-    global.crypto = tmp;
   });
src/uuid.ts (1)

3-6: Consider a more generic error message for broader environment coverage.

The error message specifically guides React Native users but this check applies to any environment without crypto.randomUUID (e.g., older Node.js versions, older browsers). Consider a more inclusive message:

💬 Suggested alternative
     throw new Error(
-      'crypto.randomUUID is not available. ' +
-      'For React Native, import "react-native-random-uuid"'
+      'crypto.randomUUID is not available. ' +
+      'Please provide a polyfill (e.g., "react-native-random-uuid" for React Native)'
     );
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b8aa51 and 7ba5b9b.

📒 Files selected for processing (3)
  • README.md
  • src/__tests__/browser-test.js
  • src/uuid.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/__tests__/browser-test.js (1)
integration/test/ParseUserTest.js (2)
  • uuidv4 (5-5)
  • require (6-6)
⏰ 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). (3)
  • GitHub Check: build (Node 24, 24.1.0)
  • GitHub Check: build (Node 20, 20.19.0)
  • GitHub Check: build (Node 22, 22.12.0)
🔇 Additional comments (1)
src/uuid.ts (1)

1-9: No changes needed. The implementation correctly assumes crypto.randomUUID is available globally in Node.js 20+ (introduced without experimental flag in v19.0.0). The error handling appropriately guards against environments where it's unavailable, such as React Native, making this a robust solution for both Node.js and React Native use cases.

Comment thread README.md
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jan 8, 2026
@dplewis
dplewis requested a review from a team January 8, 2026 17:47
@mtrezza
mtrezza requested review from Copilot and removed request for a team January 12, 2026 11:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This pull request addresses React Native build failures caused by the use of node:crypto module by migrating to the global crypto object available in modern JavaScript environments. The change allows users to polyfill crypto.randomUUID in environments where it's not natively available.

Changes:

  • Simplified UUID implementation to use global crypto.randomUUID() with runtime availability check
  • Removed environment-specific UUID generation logic (weapp, browser, Node.js)
  • Added error handling with guidance for React Native users when crypto.randomUUID is unavailable
  • Changed type definition from let to const for consistency

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 3 comments.

File Description
types/uuid.d.ts Updated type declaration from let to const to match the new implementation
src/uuid.ts Replaced environment-specific UUID implementations with a single implementation using global crypto object, throws error if unavailable
src/tests/browser-test.js Added test case to verify error handling when crypto.randomUUID is not available

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/uuid.ts Outdated
Comment thread src/uuid.ts Outdated
Comment thread src/__tests__/browser-test.js Outdated
@lawrenehi

Copy link
Copy Markdown

can someone with priv, help merge this?

@mtrezza

mtrezza commented Jan 22, 2026

Copy link
Copy Markdown
Member

@lawrenehi This requires addressing the review comments.

@dplewis

dplewis commented Jan 27, 2026

Copy link
Copy Markdown
Member Author

@mtrezza What review comments? It looks like this PR was approved.

@mtrezza

mtrezza commented Jan 27, 2026

Copy link
Copy Markdown
Member

@dplewis the copilot review comments that you just closed; please re-open them and do not close them but treat them like human feedback and respond to them; the agent will close them if you either addressed the feedback in a commit or provided a reasonable explanation for why you think the review feedback is incorrect.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Diamond Lewis <findlewis@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Diamond Lewis <findlewis@gmail.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/__tests__/browser-test.js`:
- Around line 165-174: The test in the it('throw error if randomUUID is not
available') block expects an outdated error string; update the assertion to
match the actual message thrown by src/uuid.ts (or refactor to import a shared
constant) so the expectation matches the runtime error from
require('../uuid').default(); specifically change the
expect(e.message).toBe(...) to the current message emitted by the uuid module
(or import/export a shared ERROR_MESSAGE constant from uuid.ts and use that in
the test) so they cannot drift.

Comment thread src/__tests__/browser-test.js Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jan 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 3 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/__tests__/browser-test.js Outdated
Comment on lines +171 to +174
uuidv4();
expect(true).toBe(false);
} catch (e) {
expect(e.message).toBe("crypto.randomUUID is not available in this environment. Use a UUID polyfill or environment-specific implementation (for example, in React Native you can import \"react-native-random-uuid\").");

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

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

This assertion pattern (expect(true).toBe(false)) is used to indicate that the code should have thrown an error and never reached this line. However, this pattern can be confusing and doesn't provide a clear failure message if the exception is not thrown. Consider using Jest's built-in expect(...).toThrow() matcher instead, which is more idiomatic and provides better failure messages. For example: expect(() => uuidv4()).toThrow('crypto.randomUUID is not available').

Suggested change
uuidv4();
expect(true).toBe(false);
} catch (e) {
expect(e.message).toBe("crypto.randomUUID is not available in this environment. Use a UUID polyfill or environment-specific implementation (for example, in React Native you can import \"react-native-random-uuid\").");
expect(() => uuidv4()).toThrow(
'crypto.randomUUID is not available in this environment. Use a UUID polyfill or environment-specific implementation (for example, in React Native you can import "react-native-random-uuid").'
);

Copilot uses AI. Check for mistakes.
Comment on lines +165 to +178
it('throw error if randomUUID is not available', () => {
jest.resetModules();
const tmp = global.crypto;
delete global.crypto;
try {
const uuidv4 = require('../uuid').default;
uuidv4();
expect(true).toBe(false);
} catch (e) {
expect(e.message).toBe("crypto.randomUUID is not available in this environment. Use a UUID polyfill or environment-specific implementation (for example, in React Native you can import \"react-native-random-uuid\").");
} finally {
global.crypto = tmp;
}
});

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

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

The test coverage is missing verification that the uuid module works correctly in React Native test environments. While the browser test verifies the error case when crypto is unavailable, there should also be a test in react-native-test.js (similar to the weapp test at src/__tests__/weapp-test.js:58-62) to verify that uuid generation works properly when the crypto global is available or appropriately polyfilled in React Native environments. This would ensure the module behaves correctly across all supported environments.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@coderabbitai is it even easily possible to write a React Native test in a Node.js env?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for React Native test files
fd -e js -e ts "react-native.*test" src/__tests__/

# Also search more broadly for any react-native references in test files
rg -l "react-native" src/__tests__/

# Look at the weapp test file to see what kind of test Copilot referenced
cat src/__tests__/weapp-test.js

Length of output: 2916


🏁 Script executed:

#!/bin/bash
# Check the content of react-native-test.js to see if uuid tests are present
cat src/__tests__/react-native-test.js

Length of output: 2682


@mtrezza Yes, it's definitely feasible to write React Native tests in a Node.js/Jest environment. The codebase already does this extensively in src/__tests__/react-native-test.js, which sets process.env.PARSE_BUILD = 'react-native' and mocks React Native-specific modules (like the EventEmitter, CryptoController, StorageController, etc.).

However, in this specific case, adding a React Native-specific UUID test would provide limited additional value because:

  1. The new implementation is environment-agnostic: After this PR, the uuid module simply checks for crypto.randomUUID at runtime—there's no React Native-specific code path anymore.

  2. The browser tests already cover both scenarios:

    • Success case: UUID generation when crypto.randomUUID is available (Line 158-163)
    • Error case: Throws error when crypto.randomUUID is unavailable (the new test in this PR, Line 165-179)
  3. React Native would exhibit identical behavior: Whether running in React Native or browser, the module will either use the available crypto.randomUUID (if polyfilled) or throw the same error (if not).

If you wanted to add a React Native test for consistency with other environments (like weapp has on Line 58-62), it would just verify that uuid generation works when crypto is available—essentially duplicating what the browser test already covers. The weapp test is simpler because it only checks uniqueness, not the error case.


🧬 Code Graph Analysis Results

[src/Parse.ts] 291-297

set EventuallyQueue(queue: EventuallyQueue) {
    CoreManager.setEventuallyQueue(queue);
  }

  get EventuallyQueue(): EventuallyQueue {
    return CoreManager.getEventuallyQueue();
  }

[src/Parse.ts] 135-145

export interface RESTController {
  request: (method: string, path: string, data?: any, options?: RequestOptions) => Promise<any>;
  ajax: (
    method: string,
    url: string,
    data: any,
    headers?: any,
    options?: FullOptions
  ) => Promise<any>;
  handleError: (err?: any) => void;
}

[integration/test/ParseEventuallyQueueTest.js] 4-4

const Parse = require('../../node');

[integration/test/ParseLegacyTest.js] 3-3

const { Parse } = require('../../node');

[integration/test/ParseReactNativeTest.js] 3-3

const Parse = require('../../react-native');

[integration/test/ParseReactNativeTest.js] 4-4

const { resolvingPromise } = require('../../lib/react-native/promiseUtils');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So we won't add a test here, the error message plus breaking change entry should be enough.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment thread src/uuid.ts Outdated
Comment thread src/uuid.ts
Comment on lines +1 to +9
const uuid = (): string => {
if (typeof crypto === 'undefined' || typeof crypto.randomUUID !== 'function') {
throw new Error(
'crypto.randomUUID is not available in this environment. ' +
'Use a UUID polyfill or environment-specific implementation (for example, in React Native you can import "react-native-random-uuid").'
);
}
return crypto.randomUUID();
};

Copilot AI Jan 27, 2026

Copy link

Choose a reason for hiding this comment

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

The old implementation had a custom UUID generation fallback for the 'weapp' (WeChat Mini Program) environment. The new implementation assumes that crypto.randomUUID() is available in all environments or requires a polyfill. While the test at src/__tests__/weapp-test.js:58-62 suggests UUIDs should work in weapp environments, ensure that WeChat Mini Programs actually provide the Web Crypto API with randomUUID support, or document that users need to polyfill it. If WeChat Mini Programs don't have native crypto.randomUUID support, this is a breaking change that needs to be clearly documented in the PR description and changelog.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There is no way to test in those environments, the test covers them as best as it can.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@coderabbitai how could this be tested? Or is it save to assume that no test is needed?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Find all test files related to uuid
echo "=== Finding uuid test files ==="
fd -e js -e ts uuid test

echo -e "\n=== Looking for all test files in __tests__ ==="
fd -t f . src/__tests__

echo -e "\n=== Examining weapp-test.js ==="
cat src/__tests__/weapp-test.js

echo -e "\n=== Examining browser-test.js (looking for new test) ==="
cat src/__tests__/browser-test.js

echo -e "\n=== Checking for react-native test file ==="
fd react-native-test src/__tests__

Length of output: 10643


🏁 Script executed:

#!/bin/bash

echo "=== Examining react-native-test.js ==="
cat src/__tests__/react-native-test.js

echo -e "\n=== Examining mockWeChat helper ==="
cat src/__tests__/test_helpers/mockWeChat.js

echo -e "\n=== Checking if global crypto is mocked anywhere in test setup ==="
rg -n "global\.crypto" src/__tests__/

echo -e "\n=== Checking Jest setup files ==="
fd -e json -e js jest.config . | head -5
cat jest.config.json 2>/dev/null || cat jest.config.js 2>/dev/null || echo "No Jest config found"

Length of output: 4449


@mtrezza, based on my analysis of the codebase and research into WeChat Mini Programs, here's the testing situation:

Current Testing Reality

WeChat Mini Programs don't have the Web Crypto API, and instead provide wx.getRandomValues() for secure random number generation. This means the new implementation will throw an error in real WeChat Mini Programs unless users polyfill crypto.randomUUID.

The existing test at src/__tests__/weapp-test.js:58-62 doesn't actually test the WeChat environment—it runs in Node.js (Jest), where crypto.randomUUID is available. So the test passes, but it's a false positive for the real runtime.

What CAN Be Tested

  1. Error throwing (✓ already covered): The new test in src/__tests__/browser-test.js:167-173 validates that the error is thrown when crypto is unavailable.

  2. Polyfill scenario: You could add a test that mocks global.crypto.randomUUID to verify the function works when properly polyfilled:

it('works with polyfilled crypto.randomUUID in weapp', () => {
  jest.resetModules();
  global.crypto = {
    randomUUID: jest.fn(() => '123e4567-e89b-12d3-a456-426614174000')
  };
  const uuidv4 = require('../uuid').default;
  expect(uuidv4()).toBe('123e4567-e89b-12d3-a456-426614174000');
  delete global.crypto;
});

What CANNOT Be Tested (in CI)

  • Real WeChat Mini Program runtime: As dplewis correctly noted, there's no way to run actual WeChat Mini Program tests in CI. You'd need:
    • WeChat Developer Tools simulator
    • A polyfill like wx.getRandomValues() wrapped to provide crypto.randomUUID()
    • Manual testing in the WeChat environment

Is Testing Sufficient?

Yes, with caveats:

  • The error path is tested ✓
  • The happy path (when crypto.randomUUID exists) works in Node/browser ✓
  • However, this is a breaking change for WeChat Mini Programs

Recommendations

  1. Documentation: The PR description should explicitly state this is a breaking change for WeChat Mini Programs that don't polyfill crypto.randomUUID.

  2. Migration guide: Document how WeChat users should polyfill, e.g.:

    // Polyfill for WeChat Mini Programs
    if (typeof crypto === 'undefined' || !crypto.randomUUID) {
      global.crypto = global.crypto || {};
      crypto.randomUUID = () => {
        // Implementation using wx.getRandomValues()
      };
    }
  3. Consider adding a polyfill test like the example above to document expected behavior.

The current test coverage validates the implementation works correctly in environments where it will work, but cannot test the environments where it will fail. That's acceptable given the constraints, but the breaking change needs clear documentation.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Added breaking change label to PR; so this requires a major version release and breaking change entry. What would be a concise entry without adding a whole code block?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@coderabbitai Added breaking change label to PR; so this requires a major version release and breaking change entry. What would be a concise entry without adding a whole code block?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@mtrezza, here are a few concise breaking change entry options:

Option 1 (Most concise):

**Breaking:** UUID generation now requires `crypto.randomUUID()` to be available. Environments without native support (such as WeChat Mini Programs) must provide a polyfill. See error message for environment-specific polyfill recommendations.

Option 2 (With more context):

**Breaking:** Removed custom UUID fallback for WeChat Mini Programs. UUID generation now depends on `crypto.randomUUID()` being available globally. Environments without native Web Crypto API support (WeChat Mini Programs, older React Native versions) must polyfill `crypto.randomUUID()` before using the SDK.

Option 3 (Most detailed, still concise):

**Breaking:** UUID generation refactored to use standard `crypto.randomUUID()` API. The WeChat Mini Program custom UUID implementation has been removed. Users in environments without native `crypto.randomUUID()` support must provide a polyfill (e.g., `react-native-random-uuid` for React Native, or a custom implementation wrapping `wx.getRandomValues()` for WeChat).

I'd recommend Option 1 or Option 2 as they strike the right balance between being informative and concise without overwhelming readers with implementation details.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Diamond Lewis <findlewis@gmail.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jan 27, 2026
@mtrezza mtrezza added the state:breaking Breaking change requires major version increment and `BREAKING CHANGE` commit message label Jan 28, 2026
@dplewis

dplewis commented Jan 31, 2026

Copy link
Copy Markdown
Member Author

@mtrezza we should add examples to this SDK, how else do we test tree shaking

@mtrezza

mtrezza commented Feb 8, 2026

Copy link
Copy Markdown
Member

I think if you resolve the review comments as much as you can we can go ahead and merge.

@taivara-toma

Copy link
Copy Markdown

Uh, any news on this? Seems to still be a problem in my parse 8.6.0 / react-native 0.86.2 / Expo 57 / Node 24 project

@dplewis
dplewis requested a review from mtrezza August 28, 2026 02:44
@dplewis

dplewis commented Aug 28, 2026

Copy link
Copy Markdown
Member Author

@mtrezza This is ready for review

@mtrezza

mtrezza commented Aug 29, 2026

Copy link
Copy Markdown
Member

@coderabbitai is this PR a breaking change, and if so, why?

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Changed files and diff ---'
git diff --find-renames origin/alpha...HEAD -- src/uuid.ts types/uuid.d.ts src/__tests__/browser-test.js

printf '%s\n' '--- UUID source outline ---'
ast-grep outline src/uuid.ts --items all --view expanded || true

printf '%s\n' '--- UUID source ---'
cat -n src/uuid.ts

printf '%s\n' '--- Package metadata and runtime references ---'
fd -a -t f '^(package\.json|README.*|CHANGELOG.*|COMPATIBILITY.*)$' . -E node_modules -E dist | sort
printf '%s\n' '--- Engine declarations and UUID-related documentation/references ---'
rg -n -i -C 3 '"engines"|node\s*[>=~^]|randomUUID|Web Crypto|React Native|WeChat|weapp' \
  package.json README.md CHANGELOG.md docs 2>/dev/null || true

printf '%s\n' '--- UUID imports and relevant tests ---'
rg -n -C 3 "(from ['\"].*/uuid|require\(['\"].*/uuid|randomUUID|uuid\()" src types package.json 2>/dev/null || true

Length of output: 11793


@mtrezza Yes. This is a breaking runtime compatibility change, even though the exported TypeScript signature remains () => string.

  • Node.js is not affected. package.json requires supported Node versions that provide global Web Crypto and crypto.randomUUID.
  • Browsers without crypto.randomUUID are affected. The SDK now throws instead of using any fallback.
  • WeChat is affected. The PR removes the existing PARSE_BUILD === 'weapp' UUID v4 implementation. parse/weapp now requires a global crypto.randomUUID polyfill or it throws.
  • React Native behavior changes. The change fixes the current Expo failure caused by importing Node’s crypto. However, it replaces that import-time failure with a runtime requirement: applications must provide global crypto.randomUUID before the SDK generates a UUID. React Native configurations that previously used a Node crypto shim may also need changes.

The default export is unchanged. The breaking part is the removal of platform-specific UUID implementations and the new global Web Crypto requirement.

This should be documented as breaking unless the project explicitly drops support for WeChat and all runtimes without global crypto.randomUUID.

You are interacting with an AI system.

@mtrezza

mtrezza commented Aug 29, 2026

Copy link
Copy Markdown
Member

@coderabbitai does this breaking change have any effect for the use of the SDK in https://github.com/parse-community/parse-server?

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="parse-community/parse-server"

printf '%s\n' '--- Parse Server package metadata ---'
gh api "repos/${repo}/contents/package.json?ref=master" --jq '.content' \
  | base64 --decode \
  | jq '{engines, dependencies: {parse: .dependencies.parse}, devDependencies: {parse: .devDependencies.parse}, peerDependencies: {parse: .peerDependencies.parse}}'

printf '%s\n' '--- Parse Server branches ---'
gh api "repos/${repo}/branches?per_page=100" --paginate --jq '.[].name' | sort

printf '%s\n' '--- References to the Parse SDK dependency and UUID APIs ---'
gh api "search/code?q=repo:${repo}+%28randomUUID+OR+from%3Aparse+OR+require%28%27parse%27%29%29" \
  --jq '.items[] | [.path, .html_url] | `@tsv`' 2>/dev/null || true

printf '%s\n' '--- Current SDK package compatibility metadata ---'
jq '{version, engines, exports}' package.json

Length of output: 1283


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="parse-community/parse-server"
default_branch=$(gh api "repos/${repo}" --jq '.default_branch')

printf '%s\n' '--- Repository and default branch ---'
gh api "repos/${repo}" --jq '{default_branch, archived, pushed_at}'

printf '%s\n' '--- Parse Server package metadata ---'
gh api "repos/${repo}/contents/package.json?ref=${default_branch}" --jq '.content' \
  | tr -d '\n' \
  | base64 --decode \
  | jq '{
      version,
      engines,
      dependencies: {parse: .dependencies.parse},
      devDependencies: {parse: .devDependencies.parse},
      peerDependencies: {parse: .peerDependencies.parse}
    }'

printf '%s\n' '--- Parse Server lockfile entry for parse, if present ---'
for lockfile in package-lock.json npm-shrinkwrap.json; do
  status=$(gh api -i "repos/${repo}/contents/${lockfile}?ref=${default_branch}" 2>/dev/null | head -n 1 || true)
  if printf '%s' "$status" | grep -q '200'; then
    echo "$lockfile exists"
  fi
done

printf '%s\n' '--- SDK compatibility metadata on this PR branch ---'
jq '{version, engines}' package.json

Length of output: 1893


@mtrezza No, this should not affect a user who runs Parse Server as a Node.js backend.

Parse Server currently pins its production SDK dependency to parse: "8.6.0". Therefore, installing the current Parse Server package does not install the SDK version from this PR.

If Parse Server later updates to this SDK version, the change remains compatible with Parse Server's supported Node.js versions:

  • Node.js 20.19+
  • Node.js 22.13+
  • Node.js 24.11+

These runtimes provide global Web Crypto, including globalThis.crypto.randomUUID.

The compatibility break applies to SDK consumers in runtimes without crypto.randomUUID, such as some React Native, WeChat, and older browser environments. It does not apply to the Parse Server process itself.

A Parse Server application can still have affected client code if that client separately uses the upgraded Parse SDK in one of those unsupported runtimes.

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- Parse-SDK-JS UUID implementation and package metadata ---'
ast-grep outline src/uuid.ts --items all --view expanded
cat -n src/uuid.ts
printf '%s\n' '--- Node engine and package entry points ---'
rg -n -C 3 '"engines"|"main"|"browser"|"react-native"|"weapp"' package.json

printf '%s\n' '--- Parse Server repository metadata and dependency declarations ---'
gh api repos/parse-community/parse-server --jq '{default_branch, archived, description, html_url}'
gh api repos/parse-community/parse-server/contents/package.json?ref=master --jq '.content' \
  | base64 --decode \
  | sed -n '1,260p'

printf '%s\n' '--- Parse Server references to Parse-SDK-JS UUID module or UUID generation ---'
gh api -X GET search/code \
  -f q='repo:parse-community/parse-server "parse/node"' \
  --jq '.items[] | {path, html_url}' || true
gh api -X GET search/code \
  -f q='repo:parse-community/parse-server "randomUUID"' \
  --jq '.items[] | {path, html_url}' || true

Length of output: 2810


🏁 Script executed:

#!/bin/bash
set -uo pipefail

repo='parse-community/parse-server'
ref='alpha'

printf '%s\n' '--- Parse Server package manifest on alpha ---'
gh api "repos/${repo}/contents/package.json?ref=${ref}" --jq '.content' \
  | tr -d '\n' \
  | base64 --decode \
  | sed -n '1,280p' || printf '%s\n' 'Could not retrieve package.json.'

printf '%s\n' '--- Parse Server package-lock Parse-SDK-JS resolutions, if present ---'
for file in package-lock.json npm-shrinkwrap.json yarn.lock pnpm-lock.yaml; do
  status="$(gh api "repos/${repo}/contents/${file}?ref=${ref}" --silent >/dev/null 2>&1; printf '%s' "$?")"
  if [ "$status" = 0 ]; then
    printf '%s\n' "Found ${file}"
    gh api "repos/${repo}/contents/${file}?ref=${ref}" --jq '.content' \
      | tr -d '\n' \
      | base64 --decode \
      | rg -n -C 3 '"parse"|"parse/node"|parse-community/parse' || true
  fi
done

printf '%s\n' '--- Parse Server source references to SDK entry points and uuid ---'
for query in \
  'repo:parse-community/parse-server "parse/node"' \
  'repo:parse-community/parse-server "require('\''parse'\''"' \
  'repo:parse-community/parse-server "from '\''parse'\''"' \
  'repo:parse-community/parse-server "uuid"'; do
  printf '%s\n' "Query: $query"
  gh api -X GET search/code -f q="$query" --jq '.items[] | [.path, .html_url] | `@tsv`' 2>&1 || true
done

printf '%s\n' '--- Parse Server Node engine constraints from package.json ---'
gh api "repos/${repo}/contents/package.json?ref=${ref}" --jq '.content' \
  | tr -d '\n' \
  | base64 --decode \
  | jq '{engines, dependencies: {parse: .dependencies.parse}, devDependencies: {parse: .devDependencies.parse}}' || true

Length of output: 13784


@mtrezza No, this change should not affect supported Parse Server deployments.

  • Parse Server currently pins the SDK to "parse": "8.6.0". It will not receive this change until Parse Server explicitly updates that dependency.
  • Parse Server uses the Node SDK entry point, parse/node.
  • Parse Server supports Node.js 20.19+, 22.13+, and 24.11+. These Node.js versions provide global crypto.randomUUID().

Therefore, after a Parse Server dependency update, src/uuid.ts will use the available global crypto.randomUUID() and will not throw.

The breaking effect applies to SDK runtimes without global crypto.randomUUID(), such as affected React Native, browser, and WeChat environments. It does not apply to Parse Server under its supported Node.js versions.

A deployment that runs Parse Server on an unsupported older Node.js version could fail when the SDK generates a UUID after the dependency update. Parse Server already declares those versions as unsupported, so this is not a supported compatibility concern.

You are interacting with an AI system.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state:breaking Breaking change requires major version increment and `BREAKING CHANGE` commit message

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The package at "node_modules\parse\lib\react-native\uuid.js" attempted to import the Node standard library module "crypto".

6 participants