Skip to content
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

Issue with ES Modules in firebase functions #40

Closed
ericaliebmann opened this issue Feb 10, 2024 · 4 comments
Closed

Issue with ES Modules in firebase functions #40

ericaliebmann opened this issue Feb 10, 2024 · 4 comments

Comments

@ericaliebmann
Copy link

ericaliebmann commented Feb 10, 2024

Current behavior:
Works fine in express in a traditional nodejs app

When deployed to firebase, tried both ts and vanilla js, getting this error. Have tried a number of workaround

src/index.ts:14:27 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("@passwordless-id/webauthn")' call instead.
To convert this file to an ECMAScript module, change its file extension to '.mts', or add the field "type": "module" to ____unctions/package.json'.

The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("@passwordless-id/webauthn")' call instead.
To convert this file to an ECMAScript module, change its file extension to '.mts', or add the field "type": "module" to '/_____unctions/package.json'.ts(1479)

Errors

____.min.js:1 Uncaught (in promise) FirebaseError: require() of ES Module
/workspace/node_modules/@passwordless-id/webauthn/dist/esm/index.js from /workspace/lib/index.js not supported.

Instead change the require of /workspace/node_modules/@passwordless-id/webauthn/dist/esm/index.js in /workspace/lib/index.js to a dynamic import() which is available in all CommonJS modules.

Also got this one
code: 'ERR_REQUIRE_ESM'

@ericaliebmann ericaliebmann changed the title Issue with imports in firebase functions Issue with ES Modules in firebase functions Feb 10, 2024
@dagnelies
Copy link
Collaborator

See #35 (comment)

Does that help?

@ericaliebmann
Copy link
Author

I just tried that and it did give me a different error so it's a step in the right direction

here is the tsconfig file

{
  "compilerOptions": {
    "module": "NodeNext",
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "outDir": "lib",
    "sourceMap": true,
    "strict": true,
    "target": "ESNext",
    "moduleResolution": "NodeNext"
  },
  "compileOnSave": true,
  "include": [
    "src"
  ]
}

node_modules/@passwordless-id/webauthn/dist/esm/parsers.d.ts:1:133 - error TS2835: Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './types.js'?

1 import { AuthenticatorInfo, ClientInfo, RegistrationEncoded, RegistrationParsed, AuthenticationEncoded, AuthenticationParsed } from './types';
~~~~~~~~~

node_modules/long/umd/index.d.ts:1:18 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("../index.js")' call instead.

1 import Long from "../index.js";
~~~~~~~~~~~~~

Found 2 errors in 2 files.

Errors Files
1 node_modules/@passwordless-id/webauthn/dist/esm/parsers.d.ts:1
1 node_modules/long/umd/index.d.ts:1

Error: functions predeploy error: Command terminated with non-zero exit code 2

@ericaliebmann
Copy link
Author

ericaliebmann commented Feb 13, 2024

@dagnelies That issue did help, but we had to do some slight changes #35 (comment)

3 Changes: Sharing in case you're interested, we needed to modify the build script, update package.json, and create a function which handles dynamic imports

1. Modified build script

// package.json
{
++ 
"type": "module",
"build": "esbuild src/index.ts --platform=node --bundle --target=es2022 --outfile=lib/index.js --external:util --external:cors",
...
}

also updated

// tsconfig.json
{
  "compilerOptions": {
    "module": "NodeNext",
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "outDir": "lib",
    "sourceMap": true,
    "strict": true,
    "target": "ESNext",
    "moduleResolution": "NodeNext"
  },
  "compileOnSave": true,
  "include": [
    "src"
  ]
}

2. Created function to handle the dynamic import and return the parsedRegistrations

index.ts

// index.js
/**
 * Handles the registration process for a user.
 *
 * @param {RegistrationEncoded} registration - The encoded registration data.
 * @param {string} challenge - The challenge string.
 * @return {RegistrationParsed} The credential object for the registered user.
 */
async function handleRegistration(
  registration: RegistrationEncoded,
  challenge: string,
) {
  // Import the webauthn module
  import("@passwordless-id/webauthn").then(async (module) => {
    const {server} = module;
    console.log("nodejs said, module was loaded successfully");
    const registrationParsed: RegistrationParsed =
      await server.verifyRegistration(registration, {
        challenge: challenge,
        origin: origin,
      });
    return registrationParsed;
  }).catch((error) => {
    // Handle any import errors
    console.log(error);
    return null;
  });
}

3. Return credential

const credential = await handleRegistration(registration, challenge);
return credential;

Now the packages work fine

@dagnelies
Copy link
Collaborator

Thanks for the detailed workaround. 👍

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

No branches or pull requests

2 participants