aws-sdk-js-v3 icon indicating copy to clipboard operation
aws-sdk-js-v3 copied to clipboard

dependency failures using punycode, getRandomBase64, and smithy in react-native

Open warrenronsiek opened this issue 9 months ago • 2 comments

Checkboxes for prior research

Describe the bug

When calling cognito operations (and a variety of others), the aws-sdk has a series of dependencies that are undocumented and not included in the base package.

This is closely related to https://github.com/aws/aws-sdk-js-v3/issues/4877, https://github.com/aws/aws-sdk-js-v3/issues/5736, and https://github.com/aws/aws-sdk-js-v3/issues/6013. However the workarounds suggested https://github.com/aws/aws-sdk-js-v3/issues/4877#issuecomment-1656007484, https://github.com/aws/aws-sdk-js-v3/issues/4877#issuecomment-1803353706, and https://github.com/aws/aws-sdk-js-v3/issues/6013#issuecomment-2067866695 are only part of the problem. I would expect the AWS SDK to work "out of the box" and not have to do a variety of tricks with my JS bundler, dependency hacks, and installing unlisted dependencies.

SDK version number

3.567.0

Which JavaScript Runtime is this issue in?

React Native

Details of the browser/Node.js/ReactNative version

0.74.0

Reproduction Steps

// required imports from https://github.com/aws/aws-sdk-js-v3#getting-started
import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';
// import punycode here to make sure its installed and available to the program
import 'punycode';

import { userPoolId, userPoolClientID } from "./vars";
import {
  CognitoIdentityProviderClient,
  SignUpCommand,
  AdminConfirmSignUpCommand,
  InitiateAuthCommand,
} from "@aws-sdk/client-cognito-identity-provider";
import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity";
import { fromEnv } from "@aws-sdk/credential-providers";

const region = "us-west-2";
const standardClient = new CognitoIdentityProviderClient(
  {
    region,
  });

const signUp = (email, password) => {
  const params = {
    ClientId: userPoolClientID,
    Password: password,
    Username: email,
    UserAttributes: [
      {
        Name: "email",
        Value: email,
      }],
  };
  const command = new SignUpCommand(params);
  return standardClient.send(command);
};

// Exists for testing purposes.
const adminConfirmSignup = (email) => {
  const params = {
    UserPoolId: userPoolId,
    Username: email,
  };
  const adminClient = new CognitoIdentityProviderClient(
    {
      region,
      credentials: fromEnv(),
    },
  );
  const command = new AdminConfirmSignUpCommand(params);
  return adminClient.send(command);
};

const signIn = (email, password) => {
  const params = {
    AuthFlow: "USER_PASSWORD_AUTH",
    ClientId: userPoolClientID,
    AuthParameters: {
      USERNAME: email,
      PASSWORD: password,
    },
  };
  const command = new InitiateAuthCommand(params);
  return standardClient.send(command);
};

With these functions defined, the following should fail inside of a RN application:

const email = [email protected];
const password = "P@33wordz!";
const signedUp = await signUp(email, password);
const confirmed = await adminConfirmSignup(email);
const signedIn = await signIn(email, password);

Note that this should work fine in e.g. a Jest testing environment. It just doesn't run in RN. This suggests a bundling/dependency issue.

Observed Behavior

Initially you cycle through a series of failures discussed in https://github.com/aws/aws-sdk-js-v3/issues/4877#issuecomment-1656007484. At the end, you get to Failed to construct URL with https://cognito-idp.us-west-2.amazonaws.com [TypeError: undefined is not an object (evaluating '_$$_REQUIRE(_dependencyMap[0], "punycode").ucs2.decode')] The first element in the stack refers to URLStateMachine which is in whatwg-url-without-unicode/lib/url-state-machine.js package which has a require("punycode") at the top, which seems like our culprit.

To bypass this, I hacked my node_modules/whatwg-url-without-unicode/node_modules/punycode/package.json such that the line "module": "punycode.es6.js" instead points to punycode.js. (In principle, this should be fixed by https://github.com/aws/aws-sdk-js-v3/issues/4877#issuecomment-1803353706, but for some black magic reason is not.)

Once I do this, I now get "Native module not found", "name": "Error", "stack": "getRandomBase64..." which I solved by npx pod-install (the documentation https://github.com/aws/aws-sdk-js-v3 says that they have to be imported, but doesn't mention needing to install pods or linking). Also, react-native-get-random-values does not have any bindings for windows, only android/ios. Turns out ios bindings work for macos, but android isn't sufficent. Hence, this is breaking if someone is using react-native-windows.

Now I get "Can't find variable: ReadableStream", "name": "ReferenceError", "stack": "isStreamingPayload" which seems to be the issue mentioned in https://github.com/aws/aws-sdk-js-v3/issues/5736. I solve this via stackoverflow and importing as follows:

import { ReadableStream } from 'web-streams-polyfill';
globalThis.ReadableStream = ReadableStream;

Finally, you get Can't find variable: TextDecoder as mentioned in https://github.com/aws/aws-sdk-js-v3/issues/4877#issuecomment-1803353706. Which is solved by adding the text-encoder-polyfill and import 'text-encoding-polyfill';.

Expected Behavior

AWS SDK should "just work" or be very close to it. This would imply the following:

  1. aws-sdk dependencies (a.k.a. punycode, smithy) do not have bundle resolution issues
  2. aws-sdk documentation indicates that simply importing react-native-get-random-values, should be sufficient. It doesn't mention installing pods, which is a requirement.
  3. aws-sdk should include unlisted dependencies like web-streams-polyfill and text-encoder-polyfill or at least mention these things as independent react-native requirements in the same spot it mentions react-native-get-random-values in getting started.
  4. aws-sdk should work for react-native-windows. This would involve either updating or not relying on react-native-get-random-values.

Possible Solution

No response

Additional Information/Context

No response

warrenronsiek avatar May 02 '24 22:05 warrenronsiek